1

Im having trouble figuring out how to write a multi-layer sort using a scope method in my model, which can sort through the model's attributes, as well as its related child models' attributes?

To put more concretely, I have the following models, each a related child of the previous one (I excluded other model methods and declarations for brevity):

class Course < ActiveRecord::Base 
  has_many :questions
  # would like to write multi-layer sort here 
end 

class Question < ActiveRecord::Base 
  belongs_to :course, :counter_cache => true
  has_many: :answers

end 

class Answer < ActiveRecord::Base 
  belongs_to :question, :counter_cache => true
end

I would like to sort courses first by questions_count (through my counter_cache), then by answer_count, and lastly by created_at, and was wondering how I could string everything together into a single scope method to put in my Course model.

Thanks.

daspianist
  • 5,336
  • 8
  • 50
  • 94

1 Answers1

4

As seen here (creating a scope with a joined model) : problem: activerecord (rails3), chaining scopes with includes

And here (sorting with multiple columns) : Ruby on Rails: how do I sort with two columns using ActiveRecord?

And finally here (sorting by associated model) : Rails 3. sort by associated model

You may achieve this like so :

scope :complex_sorting, lambda {
    joins(:questions)
    .order('questions_count DESC, question.answers_count DESC, created_at DESC')
}
Community
  • 1
  • 1
Raindal
  • 3,227
  • 15
  • 14
  • Typing in the code as seen above resulted in a "tried to create Proc object without a block" error. After seeing a similar issue raised, I reformatted the code as `scope :by_most_popular, lambda { |course| joins(:question).order('questions_count DESC, question.answers_count DESC, created_at DESC') }`. However, now Ruby is complaining that "wrong number of arguments (0 for 1)" – daspianist Feb 04 '13 at 00:03
  • Updated my answer to replace "do...end" with curly brackets. Do you have more precisions regarding the "wrong number of arguments error (0 for 1)" ? – Raindal Feb 04 '13 at 01:38
  • I did a bit more digging around to find out whats behind the "wrong arguments" error. I rewrote a simpler scope method to test if the joins is working (`scope :by_answer_count, -> { joins(:question).order('question.answers_count DESC') }`) and I got the error "Association named 'question' was not found; perhaps you misspelled it?". Given the way the models are related, i don't see why its can't find the `question` model. I think its likely this was throwing the more complex sorting method off. – daspianist Feb 04 '13 at 01:49
  • Just discovered that whenever I add in `|course|` to the method (the simple or complex one), I get the argument error. – daspianist Feb 04 '13 at 01:51
  • 1
    Maybe it's `:questions` and not `:question` given the `has_many` relation ? – Raindal Feb 04 '13 at 02:48
  • Thanks, this indeed happened to be the cause. However, anytime I put up the vertical bars in `|course|` I would always get the argument error. Im running ruby 1.9.3 p194.. and can't seem to figure out why it can't take the lambda. – daspianist Feb 04 '13 at 02:52
  • 1
    My mistake, I think you don't need to pass the argument (as your first error said) juste remove the `|course|`. It is used in case you pass an argument to your scope... sorry about that – Raindal Feb 04 '13 at 03:06
  • Thank you, especially for following up my questions! We are very close I think (it now renders the view instead of throwing the error). However, the part `questions.answers_count DESC` is displaying `courses` at the number of `questions` each course has.. in other words, showing repetitions of the same course. The logic seems solid, and I can't figure out why it wouldn't do as it should.. – daspianist Feb 04 '13 at 03:12
  • Ah sorry.. so currently, I only have one `Course` populated. So when I run in console `Course.all.count`, I get `=> 1`. However, when running `Course.complex_sorting.count`, I get `=>3`. The reason for this 3 is due to the fact that my Course currently has 3 questions populated.. but it seems to have taken this sum and displayed the same Course three times. – daspianist Feb 04 '13 at 05:00
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23872/discussion-between-sparda-and-daspianist) – Raindal Feb 04 '13 at 05:09