2016-03-08 11 views
5

widziałem kilka odpowiedzi na pytania, które dotyczą sposobu korzystania bloki zakresu w stowarzyszenia ActiveRecord, które należy podejmowanie sam obiekt w bloku jak ...ActiveRecord has_many poprzez skojarzenia z lunetą arg

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { baz: patron.blah }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
end 

class Bar < ActiveRecord::Base 
    belongs_to :patron, 
      ->(bar) { blah: bar.baz }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
end 

Użycie jawnego PK i FK wynika ze starszej relacji między bazowymi tabelami. W systemie produkcyjnym jest wiele setek milionów "patronów".

Jako punkt wyjaśnienia re @TJR - relacja między Patronem i Barem jest rzeczywistym złożonym kluczem obcym na polach: somekey i: baz (lub: blah w odwrotnym kierunku). Opcja ActiveRecord: foreign_key nie zezwala na tablice.

Odkryłam, że niestety to uniemożliwia późniejszą has_many: through od pracy zgodnie z oczekiwaniami.

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { baz: patron.blah }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
    has_many :drinks, through: :bars 
end 

Używanie przez stowarzyszenia produkuje błędy jak ...

ArgumentError: wrong number of arguments (0 for 1)

Związek pomiędzy barem i napojów jest klasycznym has_many ze standardowego klucza obcego i pierwotnego (bar_id, ID).

mam wymyślić kilka brzydkich arounds pracy, które pozwolą mi osiągnąć pożądaną funkcjonalność, ale cała sprawa pachnie straszne. Do tej pory najlepszy z nich wyglądają jak

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { baz: patron.blah }, 
      foreign_key: :somekey, 
      primary_key: :somekey 
    def drinks 
    bars.drinks 
    end 
end 

Dostałem istniejąca klasa Bar i składa się z wielu setek milionów rekordów, jak już wcześniej wspomniano, dzięki czemu zmiana boczny bazie trudne.

Niektóre posty zdawała się sugerować dynamiczną ocenę ciąg wewnątrz proc, aby uniknąć konieczności przechodzenia w bieżącym obiekcie patrona - ale jak wspomniano w innych postach, to nie zadziała.

Proszę mi doradzić, co mogę zrobić, aby uzyskać has_many poprzez stosunek pracy.

+0

Czy możesz zamieścić swoje prawdziwe modelu, zamiast * barów, * BAZ, * somekey * ...? Pomaga odpowiedzieć poprawnie. –

+0

Nie jestem jasny na temat tego, co próbuje osiągnąć zasięg stowarzyszenia has_many. Czy nie możesz użyć opcji klucza obcego, aby określić kolumnę pręta, która zawiera klucz podstawowy użytkownika ze względu na przywołane wcześniej przyczyny? TO ZNACZY. robi coś takiego jak 'has_many: bars, foreign_key:" some_column_on_bar_storing_patron_id "' nie działa? Choć ze scenariusza już wskazano, ja również zastanawiam się, czy czytelnika i Bar sami powinni mieć has_many za pośrednictwem relacji, jak również (to zależy od spuścizny można wymienić, ale bary mają tylko jeden patron? Czy to nie jest dosłowny bar?) – TJR

+0

Relacja między patronem a słupkiem jest faktycznie realizowana przez złożoną relację klucza obcego. Ponieważ opcja: foreign_key nie akceptuje tablicy pól, zmuszony jestem użyć bloku zasięgu, aby osiągnąć drugą część złożonego klucza obcego. –

Odpowiedz

0

Właśnie próbowałem tego rodzaju stowarzyszeń w Rails 4.2. To działa bardzo dobrze:

class Patron < ActiveRecord::Base 
    has_many :bars, 
      ->(patron) { where(baz: patron.blah) }, 
      foreign_key: :patron_id, 
      primary_key: :id 

    has_many :drinks, through: :bars 
end 

class Bar < ActiveRecord::Base 
    belongs_to :patron, 
      ->(bar) { where(blah: bar.baz) }, 
      foreign_key: :patron_id, 
      primary_key: :id 

    has_many :drinks 
end 

class Drink < ActiveRecord::Base 
end 

Sprawdź stowarzyszenia:

> p1 = Patron.first 
> p1.drinks 
    Drink Load (0.8ms) SELECT "drinks".* FROM "drinks" INNER JOIN "bars" ON "drinks"."bar_id" = "bars"."id" WHERE "bars"."patron_id" = 1 AND "bars"."baz" = 1 [["patron_id", 1], ["baz", 1]] 
=> #<ActiveRecord::Associations::CollectionProxy [#<Drink id: 3, name: "drink 3", bar_id: 2, created_at: "2017-04-07 03:30:06", updated_at: "2017-04-07 03:30:06">]> 
Powiązane problemy