Ostrzeżenie o wycofaniu podczas używania has_many: through: uniq w Railsach 4

95

Rails 4 wprowadził ostrzeżenie o wycofaniu podczas używania: uniq => true z has_many: through. Na przykład:

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

Daje następujące ostrzeżenie:

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'

Jaki jest poprawny sposób przepisania powyższej deklaracji has_many?

Ryan Crispin Heneise
źródło

Odpowiedzi:

237

uniqOpcja musi być przeniesiona do bloku zakres. Zwróć uwagę, że blok zakresu musi być drugim parametrem has_many(tj. Nie możesz go zostawić na końcu linii, należy go przesunąć przed :through => :donationsczęścią):

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

Może to wyglądać dziwnie, ale ma to trochę więcej sensu, jeśli weźmiesz pod uwagę przypadek, w którym masz wiele parametrów. Na przykład to:

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

staje się:

has_many :donors, -> { where("age < 30").order("name").uniq }, :through => :donations
Dylan Markow
źródło
Dzięki, to działa świetnie! Gdzie to znalazłeś? Nie udało mi się go nigdzie znaleźć w dokumentacji.
Ryan Crispin Heneise
6
Właściwie widziałem to w książce Upgrading to Rails 4 (w toku): upgradingtorails4.com - nie mogłem go znaleźć nigdzie indziej.
Dylan Markow
1
@DylanMarkow link do Aktualizacji do Rails 4 nie istnieje. Książka została wydana na licencji CC pod adresem github.com/alindeman/upgradingtorails4
Ivar
1
W przypadku Rails 5 użyj distinctzamiast uniq. Zobacz tę odpowiedź, aby uzyskać więcej informacji.
Nic Nilov
5

Oprócz odpowiedzi Dylansa, jeśli zdarza się, że rozszerzasz powiązanie z modułem, upewnij się, że łączysz go w bloku zasięgu (w przeciwieństwie do określania go osobno), na przykład:

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

Może to tylko ja, ale wydaje się bardzo nieintuicyjne użycie bloku zasięgu do rozszerzenia proxy asocjacji.

Andrew Hacking
źródło