Сложная ассоциация ActiveRecord.Проходя через 4 стол - PullRequest
0 голосов
/ 22 апреля 2010

У меня сложный случай, и мне интересно, как это будет работать в рельсах:

Я хочу классифицировать жанры некоторых певцов.Исполнители могут принадлежать к нескольким жанрам, и пользователи могут назначать теги для каждого жанра

Например:

singers  <-- singers_genres --> genres <-- genres_tags --> tags

SQL будет выглядеть примерно так:

SELECT * FROM singers S 
     INNER JOIN singers_genres SG ON S.id=SG.singer_id
     INNER JOIN genres G ON G.id = SG.genre_id
     LEFT OUTER JOIN genre_tags GT ON G.id = GT.genre_id
     INNER JOIN tags T ON GT.tag_id = T.id

Вот как выглядят мои классы:

class Singer
   has_and_belongs_to_many :genres, :include => :tag

class Genre
   has_and_belongs_to_many :singers
   has_and_belongs_to_many :tags

class Tag
   has_and_belongs_to_many :genres

Ответы [ 2 ]

1 голос
/ 22 апреля 2010

Давайте создадим проект ...

rails itunes
cd itunes

Создание базовых моделей:

script/generate model Singer name:string
script/generate model Genre name:string
script/generate model Tag name:string

выполнить миграцию:

rake db:migrate

обновить модели:

class Singer < ActiveRecord::Base
  has_and_belongs_to_many :genres
end

class Genre < ActiveRecord::Base
  has_and_belongs_to_many :singers
  has_and_belongs_to_many :tags
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :genres
end

создать еще две миграции для объединения таблиц:

script/generate migration CreateGenresSingersJoin
script/generate migration CreateGenresTagsJoin
rake db:migrate

модель genres_singers:

class CreateGenresSingersJoin < ActiveRecord::Migration
  create_table 'genres_singers', :id => false do |t|
    t.integer 'genre_id'
    t.integer 'singer_id'
  end

  def self.down
    drop_table'genres_singers'
  end
end

модель genres_tags:

class CreateGenresTagsJoin < ActiveRecord::Migration
  create_table 'genres_tags', :id => false do |t|
    t.integer 'genre_id'
    t.integer 'tag_id'
  end

  def self.down
    drop_table'genres_tags'
  end
end

создать некоторые данные о посеве в seed.db или любым другим способом:

Singer.create(:name => 'Lady Ga Ga')
Genre.create(:name => 'Pop')
Genre.create(:name => 'Folk')
Tag.create(:name => 'Top50')

вставить некоторые данные ссылки:

INSERT INTO genres_singers (genre_id, singer_id) VALUES (1, 1)
INSERT INTO genres_singers (genre_id, singer_id) VALUES (2, 1)
INSERT INTO genres_tags (genre_id, tag_id) VALUES (1, 1)

тогда мы можем использовать ассоциации, например:

Singer.first.genres.first.tags.first
=> #<Tag id: 1, name: "Top50">

Singer.find_by_name("Lady Ga Ga").genres.first.tags
=> [#<Tag id: 1, name: "Top50">]
0 голосов
/ 22 апреля 2010

Выбор между has_many: through и has_and_belongs_to_many - хорошее введение в ассоциации.

Возможно, вы можете опубликовать здесь свои модели, чтобы увидеть, как создаются ассоциации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...