Я пытаюсь понять, как ActiveRecord работает с ассоциациями, которые являются более сложными, чем простые has_many
, belongs_to
и т. Д.
В качестве примера рассмотрим приложение для записи музыкальных концертов. У каждого концерта есть группа, которая имеет жанр. У каждого концерта также есть Место проведения, в котором есть Регион.
В грубой нотации 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}
во второй модели жанра фактически возвращает идентификатор класса. (Я думаю). Тем не менее, похоже, что это работает здесь и здесь
Я понимаю, что это довольно эпичный вопрос, так что спасибо, если вы дошли до этого. Любая помощь будет принята с благодарностью!