Deprecated warning for Rails 4 has_many with order
Solution 1
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
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
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.
Related videos on Youtube
shankardevy
Updated on March 05, 2021Comments
-
shankardevy about 3 years
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.
-
shankardevy over 10 yearsworks superb! where can I find such information in the guides or docs? I can't find one. thanks.
-
Joshua Coady over 10 years
-
kakubei over 10 yearsWhat about if you have more than one deprecated option, say
oder
andinclude
? This:{ order(:position), include(:track) }
throws error on the comma. -
wspruijt about 10 yearsFor ordering asc/desc, use
-> { order(name: :asc) }
-
Grzegorz Łuszczek over 9 yearsDon't use default scope. If you're used to do it, you can add in that magic method more logic. It's hard to override it in future.
-
Dirty Henry almost 9 yearsIf for some reason, you just want the collection to be ordered some times, you can also do
list.contents.order('position desc')
which can be more efficient overall, and not as model intrusive (in the voted answer, list knows a field of content, here the controller knows it) -
JosephK almost 9 yearsThis gives me an error "syntax error, unexpected '\n', expecting =>" - - but there is no "=>" using the new method, stated here. Using wspruijt's version, I get the error, "syntax error, unexpected tLABEL ... , -> { order (created_at: :desc) }". Pity the older, clearer syntax is now dumped by Rails 4 in favor of this gibberish. Seems if you have any other conditions, they must all go into some curly-bracket spasm, or you can't do ordered-sorts on the model, anymore.
-
Major Major over 6 yearsThis is also true of "through" associations that might exist on the object -
has_many :items, -> { order 'name' }, through: :suppliers
-
timothyashaw over 6 yearsThis was exactly my issue. Trying to figure out how to order a has_many relationship by a parent attribute. Didn't realize you can do includes like this and then order. Thanks!
-
Matrix over 2 yearsthx, I just search with dependent option too !! THX