0

I want to order the Conversation model, using a custom method.

I found some solution:

How do you order by a custom model method that has no attribute in SQL?

and

http://awaxman11.github.io/blog/2013/10/11/sorting-a-rails-resource-based-on-a-calculated-value/ ,

but Conversation order have priority.

First- answer_percent desc, second- order to last_answer time (using custom model method last_answered_to_i ).

last_answered_to_i method source:

def last_answered_to_i
  if Conversation.where(company_id: self.id, is_answered: true).present?
    last_conversation = Conversation.where(company_id: self.id, is_answered: true).first
    if last_conversation.answered_at.blank? || last_conversation.asked_at.blank?
      minutes =  (Time.now- last_conversation.updated_at)/1.minutes
    else
      minutes =  (last_conversation.answered_at - last_conversation.asked_at)/1.minutes
    end
    minutes.to_i
  else
    nil
  end
end

after ordering I want add pagination using kaminari gem.

@lists = Company.searchable.order("answer_percent desc").page(params[:page]).per(20)

How do I order by column and custom method and add pagination?

Community
  • 1
  • 1
kai
  • 492
  • 3
  • 18
  • what do your relationships look like for `Conversation` to `Company` seems you could handle this with a scope depending. Also where is `last_answered_to_i` defined? – engineersmnky Jan 21 '15 at 15:42
  • @engineersmnky Company has_many Conversation and method defind Conversation Model – kai Jan 21 '15 at 15:47
  • So you want to return all the conversations for a company or for all companies? sorted by `[-conversation.answer_percentage,conversation.last_answered_to_i]`? Just trying to understand the desired output so that I can devise an appropriate answer. – engineersmnky Jan 21 '15 at 16:20
  • @engineersmnky Yes I wanna sort by [-conversation.answer_percentage,conversation.last_answered_to_i]. And result ActiveRecord is Conversation for all company – kai Jan 22 '15 at 08:50
  • @engineersmnky Sort by All Company using Company's all conversation answer percent( simply answer_count / question_count * 100) and companys last conversation's answered Term(using last_answered_to_i) – kai Jan 22 '15 at 08:53

1 Answers1

0

I think the answer depends on what you want to see in the view because some of the problem could actually be solved in how you call @lists there. Also, some of the links you found make sorting by a model method sound more difficult than it is.

In your case, you can sort your conversations by a custom method like so: Conversation.all.sort_by(&:custom_method)

Or specifically: Conversation.all.sort_by(&:last_answered_to_i)

Specifically, you cannot use SQL to sort or order by something not in the actual database, so you use the Ruby sort_by method. For more info on the ampersand, see this post.

For your actual view, I'm not sure really how you want to organize it. I recently did something where I needed to group my resource by another resource called "categories", and then sort the original resource by "netvotes" which was a custom model method, then order by name. I did it by:

  • Ordering by name in the controller: @resources = Resource.order(:name)
  • Grouping by category in the outer loop of the view: <% @resources.group_by(&:category).each do |category, resources| %>
  • Then sorting the resources by votes in the partial for resources: <%= render resources.sort_by(&:netvotes).reverse %>

The view is a bit confusing, so here is the full view loop in index.html.erb:

<% @resources.group_by(&:category).each do |category, resources| %>
  <div class="well">
    <h3 class="brand-text"><%= category.name %></h3>
    <%= render resources.sort_by(&:netvotes).reverse %>
  </div>
<% end %>

And here is the _resource.html.erb partial:

<div class="row resource">
  <div class="col-sm-2 text-center">
    <div class="vote-box">
      <%= link_to fa_icon('chevron-up lg'), upvote_resource_path(resource), method: :put %><br>
      <%= resource.netvotes %><br>
      <%= link_to fa_icon('chevron-down lg'), downvote_resource_path(resource), method: :put %>
    </div>
  </div>
  <div class="col-sm-10">
    <%= link_to resource.name, resource.link, target: "_blank" %>
    <p><%= resource.notes %></p>
  </div>
</div>

I hope that helps you think through some more ways to address your problem.

Sia
  • 8,894
  • 5
  • 31
  • 50