Przeczytałem: http://guides.rubyonrails.org/association_basics.html
i próbuję zrozumieć zasadę działania parametru :source w relacjach has_many :through porównując go z parametrem :foreign_key.
Jak dla mnie te parametry działają dokładnie w ten sam sposób (pomijając to, że do :foreign_key trzeba podać pełną nazwę kolumny wraz z sufixem _id).
Czy :source jest po prostu odpowiednikiem :foreign_key w relacjach has_many :through?
Czy są może jeszcze inne różnice których nie zauważyłem?
I tak i nie. Generalnie :source wskazuje na relacje, docelową i przydaje się jak na przykład n-n jako self join (czyli na przykąłd modelujesz graf). Generalnie opcja jest bardzo bardzo rzadko wykorzystywana, próbowałem nawet wymyślić jakis przykład ale nic trywialnego nie przychodzi do głowy.
Właśnie tak robię, relację wiele do wielu, gdzie model Relationship łączy model User z modelem User.
A jeszcze takie pytanie (na podstawie kodu z tutoriala):
class User < ActiveRecord::Base
has_many :relationships, :foreign_key => “follower_id”, :dependent => :destroy
has_many :following, :through => :relationships, :source => :followed
has_many :reverse_relationships, :foreign_key => “followed_id”, :class_name => “Relationship”, :dependent => :destroy
has_many :followers, :through => :reverse_relationships, :source => :follower
end
Jeśli dobrze rozumiem to:
@user1.following << @user2
utworzy obiekt Relationship i nada mu wartości atrybutów przez mass assignment. Czy można w ten sposób podać wartości dodatkowych atrybutów modelu Relationship?
Opcja source moze sie przydac, kiedy model posredni ma asocjacje polimorficzna:
class Person < ActiveRecord::Base
has_many :memberships
has_many :schools, :through => :memberships, :source => :group, :source_type => “School”
has_many :families, :through => :memberships, :source => :group, :source_type => “Family”
end
class Membership < ActiveRecord::Base
belongs_to :person
belongs_to :group, :polymorphic => true
end
_johny: zwróć uwagę na słowo “trywialny”. Zgadzam się że jest przydatny, ale bardzo rzadko się go używa, i jest zwykle znakiem że ktoś przekombinował z projektem bazy danych.
kkrol. Tak na przykłąd przez @user1.relationships.create(:follower_id => @user2, :dodatkowy => ‘atrybut’)
Generalnei :source jest tak jakby przeciwieństwem dla :foreign:key. jak w twoim przykłądzie możesz zapisać:
has_many :followers, :through => :reverse_relationships, :source => :follower, :foreign_key => ‘followed_id’
Dzięki, już to zrozumiałem.
Zastanawiałem się jednak, czy można operować na atrybutach tej tabeli łączącej: relationships nie używając w ogóle:
has_many :relationships
a jedynie:
has_many :following, :through => :relationships
ale przejrzałem wiele projektów i widzę, że dołączenie obu deklaracji:
has_many :relationships
has_many :following, :through => :relationships
jest dobrą praktyką.
kkrol: nie tylko dobrą praktyką, jest konieczne!
Generalnie :through wskazuje na inną relację - która musi zostać uprzednio zdefiniowana!
Czyli nie możesz zrobić po prostu has_many :following, :through => :relationships o ile nie zdefiniujesz relacji relationships