Sort_by more than one field - one is a boolean!

So I am retrieving a dataset of blog posts from DatoCMS using the dato gem and the paginate gem. This is being done in the config.rb to generate pages of blog posts. I want to sort them by date_published obviously but I also want to put the ‘sticky’ posts at the top (note to self, I want to swap the order that I call the sort fields and sort by issticky first!! lol). I thought I had figured it out (the syntax was killing me) , however when i used a boolean to sort by (namely:issticky) I find that ruby doesn’t support ordering by boolean field!. I found the work around whereby you change the boolean values into a 0 or 1 and then ruby will sort by integers but I am getting following error.

`block in evaluate_configuration!’: wrong argument type Integer (expected Proc) (TypeError)

Can anyone help or suggest another way to get same result. Not sure if I am nearly there, just an issue with syntax or if i am wasting time with this approach

dato.tap do |dato|
paginate dato.blogs.sort_by(&:date_published && :issticky ? 0 : 1), "/blog", "/templates/blogs.html", per_page: 10
end

Can anyone help
@tomrutgers can you weigh in on this at all, you seem to know your way around the beast I call ruby!! lol

How about a combination of select and sort_by?

dato.tap do |dato|
  blogs = []
  sticky_blogs = data.blogs.select {|blog| blog.issticky}.sort_by(&:date_published)
  non_sticky_blogs = data.blogs.select {|blog| !blog.issticky}.sort_by(&:date_published
  blogs.push(sticky_blogs, non_sticky_blogs)

  paginate blogs, "/blog", "/templates/blogs.html", per_page: 10
end

Tom

That seemed like a pretty neat solution. Unfortunately it broke the proxies, i.e. the references to individual values in the items array where not found, and the pagination didn’t work

its like middleman didn’t see the blogs array in the same way it sees recordsets or something

<% items.each_with_index do |blog, i| %> - this is how I loop through the resulting blogs on the template page
<div class="blog-post">	
<% case blog.blog_type.slug %> - blog.blog_type wasn't recognised etc
<% when "no-image" %>

So I feel it has to be some sort of sorting by two fields at once? or else some kind of remedial work on the template page to work with the new format of data that it is getting sent to it?
Dave

TOm

FYI I also had to change it to this to get DESC order newest posts first! lol

paginate dato.blogs.sort {|x,y| y.date_published <=> x.date_published}

What does blogs.push do in terms of creating an array?? and is it recognised by paginate gem as a valid recordset that I can pull various fields from?
Dave

undefined method `blog_type’ for #Array:0x00007fa4fddb78c0

I’ve tried a few versions of this and i’m going to stick with it because judging by the output in console when i check the content of blogs variable it looks like it has retrieved them correctly and in the correct order DESC etc, however I’m am stumped why none of the fields are available on the template page.

This what I have currently

dato.tap do |dato|
blogs = []
sticky_blogs = dato.blogs.select {|blog| blog.issticky}.sort {|x,y| y.date_published <=> x.date_published}
non_sticky_blogs = dato.blogs.select {|blog| !blog.issticky}.sort {|x,y| y.date_published <=> x.date_published}
blogs.push(sticky_blogs, non_sticky_blogs)
  #puts sticky_blogs
  #puts non_sticky_blogs
  #puts blogs
  paginate blogs, "/blog", "/templates/blogs.html", per_page: 5
end

on the template page:

<% items.each do |blog| %
			<div class="blog-post">	
		
				<% case blog.blog_type.slug %>
				<% when "no-image" %>
					<div class="post-teaser">
						<div class="post-meta">
							<time datetime="<%= blog.date_published.strftime('%F') %>"><%= blog.date_published.strftime('%b %e %Y') %></time>
							<p class="post-meta-author">by <a href="#">Ballymena Nursery</a></p>
							<p class="post-meta-author">
							Posted in
							<% blog.topic.each do |topic| %>
								<a href="/blog/topics/<%= topic.slug %>/" rel="tag"><%= topic.title %></a>
								<% if !topic.equal?(blog.topic.last)%>,<% end %>
							<% end %>
							</p>								
						</div>
						<a href="/blog/<%= blog.slug %>/" class="post-title"><%= blog.title %></a>
						<p class="short-text"><%= truncate_words(blog.blog_content, :length => 30) %></p>
						
					</div>
				<% when "single-image" %> etc etc

this is the middleman-paginate gem i use : https://github.com/cantierecreativo/middleman-paginate

UPDATE: this works

  paginate dato.blogs.select {|blog| !blog.issticky}.sort {|x,y| y.date_published <=> x.date_published}, "/blog", "/templates/blogs.html", per_page: 5 
  • the non sticky only blogs are paginated correctly and sorted in DESC order of date published, but if I use the blogs.push method I can no longer access any of the data by the same references in any case on the template page. Any ideas?

this doesn’t

paginate blogs, "/blog", "/templates/blogs.html", per_page: 5

Tom

I got there in the end with this

 dato.tap do |dato|
   blogs = []
   sticky_blogs = dato.blogs.select {|blog| blog.issticky}.sort {|x,y| y.date_published <=> x.date_published}
   non_sticky_blogs = dato.blogs.select {|blog| !blog.issticky}.sort {|x,y| y.date_published <=> x.date_published}
   blogs = sticky_blogs.union(non_sticky_blogs)
   paginate blogs, "/blog", "/templates/blogs.html", per_page: 5
 end

I guess the blogs.push method must do some crazy ‘foo’ that breaks the pagination gem code???

I really wouldn’t have got there without you though buddy, so thanks for the assist! lol :wink:

Maybe there were some nil entries pushed to the array as well, breaking the paginate script? Not sure. Glad you figured it out though!