Avertissement de dépréciation lors de l'utilisation de has_many: through: uniq dans Rails 4

95

Rails 4 a introduit un avertissement de dépréciation lors de l'utilisation de: uniq => true avec has_many: through. Par exemple:

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

Renvoie l'avertissement suivant:

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'

Quelle est la bonne façon de réécrire la déclaration has_many ci-dessus?

Ryan Crispin Heneise
la source

Réponses:

237

L' uniqoption doit être déplacée dans un bloc d'étendue. Notez que le bloc de portée doit être le deuxième paramètre de has_many(c'est- à -dire que vous ne pouvez pas le laisser à la fin de la ligne, il doit être déplacé avant la :through => :donationspièce):

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

Cela peut sembler étrange, mais cela a un peu plus de sens si vous considérez le cas où vous avez plusieurs paramètres. Par exemple, ceci:

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

devient:

has_many :donors, -> { where("age < 30").order("name").uniq }, :through => :donations
Dylan Markow
la source
Merci, cela fonctionne très bien! Où as tu trouvé ça? Je n'ai pu le trouver nulle part dans la documentation.
Ryan Crispin Heneise
6
Je l'ai vu dans le livre Upgrading to Rails 4 (il est en cours): upgradeingtorails4.com - je n'ai pu le trouver nulle part ailleurs.
Dylan Markow
1
@DylanMarkow le lien pour la mise à niveau vers Rails 4 est obsolète. Le livre est maintenant publié sous une licence CC sur github.com/alindeman/upgradingtorails4
Ivar
1
Avec Rails 5, utilisez à la distinctplace de uniq. Voir cette réponse pour plus de détails.
Nic Nilov
5

En plus de la réponse de Dylans, si vous étendez l'association avec un module, assurez-vous de l'enchaîner dans le bloc de portée (au lieu de le spécifier séparément), comme ceci:

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

Peut-être que c'est juste moi, mais il semble très peu intuitif d'utiliser un bloc de portée pour étendre un proxy d'association.

Andrew Hacking
la source