1

Let's say I run an ActiveRecord query and it returns 3 results, with a bunch of attributes.

I want to add 3 attributes to each record in the Array so I can do sorting at a code-level. These 3 include: num_comments, num_views, last_view.

  1. How do I add these attributes?
  2. How do I then sort the records, in order of precendence, by num_comments AND by num_views AND by last_view?

2 Answers 2

3
# file a_model_class (AR subclass)
   attr_accessor :num_comments, :num_views, :last_view # add setters and getters

# different file that is doing the fetch and sort...
results = AModelClass.find.... # 3 results
results.each{|r|
  r.num_comments = x  # set the instance variables for sorting
  r.num_views = y
  r.last_view = z
}

# now sort
sorted_results = results.sort{|a,b|
  r = a.num_comments <=> b.num_comments 
  r = a.num_views <=> b.num_views if r == 0
  r = a.last_view <=> b.last_view if r == 0
}

# sorted_results is sorted copy of results
Sign up to request clarification or add additional context in comments.

1 Comment

sorting can be optimized into simple sorted_results = results.sort_by{ |r| [r.num_comments, r.num_views, r.last_view] }
1

Expanding on Larry K's answer and zed_0xff's comment, why even create attributes, just sort by a method in your model:

class Widget < ActiveRecord::Base
  def num_comments
    #count comments
  end

  def num_views
    #count views
  end

  def last_view
    #return last view
  end
end

in your controller

class WidgetsController < ApplicationController
  def index
    @widgets = Widget.all.sort_by{ |r| [r.num_comments, r.num_views, r.last_view] }
  end
end

2 Comments

Main thing to watch out for here is to NOT re-compute the values (num_comments, etc) each time the methods (num_comments, etc) are called. Since those methods will be called many times during the sort, they need to cache their values. Using instance variables will explicitly ensure this. I agree with you that the computation of the values should probably be handled from within the model, not externally.
Ahhh, good point, I didn't even think of that. I'll refactor my answer a bit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.