Я пытаюсь понять, как ActiveRecord имеет дело с ассоциациями, которые сложнее, чем простые has_many
, belongs_to
и так далее.Сложные ассоциации в моделях ActiveRecord
В качестве примера рассмотрим приложение для записи музыкальных концертов. У каждого Gig есть группа, в которой есть жанр. У каждого концерта также есть место, в котором есть регион.
В грубом обозначениях MS Access (которые я вдруг начала чувствовать себя довольно ностальгическим для) эти отношения будут представлены, как это
1 ∞ 1 ∞ ∞ 1 ∞ 1
Genre ---- Band ---- Gig ---- Venue ---- Region
Я хотел бы иметь возможность узнать, например, , все группы, которые играли в регионе, или все места, где размещается определенный жанр.
В идеале, мои модели будут содержать этот код
class Genre
has_many :bands
has_many :gigs, :through => bands
has_many :venues, :through => :gigs, :uniq => true
has_many :regions, :through => :venues, :uniq => true
end
class Band
belongs_to :genre
has_many :gigs
has_many :venues, :through => :gigs, :uniq => true
has_many :regions, :through => :venues, :uniq => true
end
class Gig
belongs_to :genre, :through => :band
belongs_to :band
belongs_to :venue
belongs_to :region, :through => :venue
end
и так далее для Venue
и Region
.
Тем не менее, кажется, я должен производить что-то вроде этого вместо
class Genre
has_many :bands
has_many :gigs, :through => bands
has_many :venues, :finder_sql => "SELECT DISTINCT venues.* FROM venues " +
"INNER JOIN gigs ON venue.id = gig.venue_id " +
"INNER JOIN bands ON band.id = gig.band_id " +
"WHERE band.genre_id = #{id}"
# something even yuckier for regions
end
class Band
belongs_to :genre
has_many :gigs
has_many :venues, :through => :gigs, :uniq => true
# some more sql for regions
end
class Gig
delegate :genre, :to => :band
belongs_to :band
belongs_to :venue
delegate :region, :to => :venue
end
У меня есть два вопроса - один общий и один конкретный.
Общее:
я бы подумал, что я пытался сделать бы придумать довольно часто. Это то, что у меня есть на самом деле лучший способ сделать это, или есть что-то намного более простое, что я пропускаю?
Конкретная:
То, что я выше на самом деле не совсем работает! #{id}
во второй жанровой модели действительно возвращает идентификатор класса. (Я думаю). Однако, похоже, это работает here и here
Я понимаю, что это довольно эпический вопрос, так что спасибо, если у вас это далеко. Любая помощь будет принята с благодарностью!