Deprecated warning for Rails 4 has_many with order

Ruby on-RailsRuby on-Rails-4

Ruby on-Rails Problem Overview


class RelatedList < ActiveRecord::Base
  extend Enumerize

  enumerize :list_type, in: %w(groups projects)

  belongs_to :content
  has_many :contents, :order => :position

end

I have this model in my rails app which throws warning when I try to create records in console.

> DEPRECATION WARNING: The following options in your > RelatedList.has_many :contents declaration are deprecated: :order. > Please use a scope block instead. For example, the following: has_many > :spam_comments, conditions: { spam: true }, class_name: 'Comment' > should be rewritten as the following: has_many :spam_comments, -> { > where spam: true }, class_name: 'Comment' > . (called from at /Users/shivam/Code/auroville/avorg/app/models/related_list.rb:7)

It seems like Rails 4 has new :order syntax for use in models but I can't seem to find the documentation in Rails Guides.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

In Rails 4, :order has been deprecated and needs to be replaced with lambda scope block as shown in the warning you've posted in the question. Another point to note is that this scope block needs to be passed before any other association options such as dependent: :destroy etc.

Give this a try:

has_many :contents, -> { order(:position) } # Order by :asc by default

To specify order direction, i.e. either asc or desc as @joshua-coady and @wsprujit have suggested, use:

has_many :contents, -> { order 'position desc' }

or, using the hash style:

has_many :contents, -> { order(position: :desc) }

Further reference on Active Record Scopes for has_many.

Solution 2 - Ruby on-Rails

It took me a while to figure out how to do order and include, I eventually found that you chain the scope statements,

has_many :things, -> { includes(:stuff).order("somedate desc") }, class_name: "SomeThing"

Solution 3 - Ruby on-Rails

Just thought I'd add that if you have any option hash arguments, they have to go after the lambda, like this:

has_many :things, -> { order :stuff }, dependent: :destroy

Took me a minute to figure this out myself - hopefully it helps anyone else coming to this question having the same problem.

Solution 4 - Ruby on-Rails

This works for me with Rails 4 & MongoDB

has_many :discounts, order: :min_amount.asc

Solution 5 - Ruby on-Rails

Alternatively, you can put the order clause on the model, for instance:

has_many :options, order: 'name' # In class Answer

Becomes

has_many :options # In class Answer

default_scope { order 'name' } # In class Option

PS: I got ArgumentError: wrong number of arguments (1 for 0) when doing has_many :things, -> {}.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionshankardevyView Question on Stackoverflow
Solution 1 - Ruby on-RailsveeView Answer on Stackoverflow
Solution 2 - Ruby on-RailssfoopView Answer on Stackoverflow
Solution 3 - Ruby on-RailsWylliam JuddView Answer on Stackoverflow
Solution 4 - Ruby on-RailsDaveView Answer on Stackoverflow
Solution 5 - Ruby on-RailsDorianView Answer on Stackoverflow