Deprecation warning when using has_many :through :uniq in Rails 4

Ruby on-RailsActiverecordRails ActiverecordRuby on-Rails-4

Ruby on-Rails Problem Overview


Rails 4 has introduced a deprecation warning when using :uniq => true with has_many :through. For example:

has_many :donors, :through => :donations, :uniq => true

Yields the following warning:

DEPRECATION WARNING: The following options in your Goal.has_many :donors declaration are deprecated: :uniq. 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'

What is the correct way to rewrite the above has_many declaration?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

The uniq option needs to be moved into a scope block. Note that the scope block needs to be the second parameter to has_many (i.e. you can't leave it at the end of the line, it needs to be moved before the :through => :donations part):

has_many :donors, -> { uniq }, :through => :donations

It may look odd, but it makes a little more sense if you consider the case where you have multiple parameters. For example, this:

has_many :donors, :through => :donations, :uniq => true, :order => "name", :conditions => "age < 30"

becomes:

has_many :donors, -> { where("age < 30").order("name").uniq }, :through => :donations

Solution 2 - Ruby on-Rails

In addition to Dylans answer, if you happen to be extending the association with a module, make sure that you chain it in the scope block (as opposed to specifying it separately), like so:

has_many :donors,
  -> { extending(DonorExtensions).order(:name).uniq },
  through: :donations

Maybe its just me but it seems very unintuitive to use a scope block to extend an association proxy.

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
QuestionRyenskiView Question on Stackoverflow
Solution 1 - Ruby on-RailsDylan MarkowView Answer on Stackoverflow
Solution 2 - Ruby on-RailsAndrew HackingView Answer on Stackoverflow