DesignAssembler

備忘録に近い

n対nの関連

Railsでn対n関連を実装します。

現在1対nの関連を持ったTagテーブルとArticleテーブルをn対nの関連に変更します。

ここでは中間テーブルを作成しない方法で実装します。

has_and_belongs_to_many

各モデルにhas_and_belongs_to_manyを追加します。

class Article < ActiveRecord::Base
  has_and_belongs_to_many :tags
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

関連付け

関連付けはマイグレーションファイルで行います。

キー指定は必要なくなるのでarticle_idとtag_idは必要なくなります。ですので削除します。

$ rails g migration remove_article_id_from_tags article_id:integer
$ rails g migration remove_tag_id_from_articles tag_id:integer

以下のコマンドでマイグレーションファイルを生成します。

$ rails g migration create_articles_tags

こんな感じでActiveRecord::Associations::CollectionProxyクラスのオブジェクトとして関連付けが形成されます。

irb(main):001:0> Article.first.tags
  Article Load (0.4ms)  SELECT  `articles`.* FROM `articles`  ORDER BY `articles`.`id` ASC LIMIT 1
  Tag Load (0.4ms)  SELECT `tags`.* FROM `tags` INNER JOIN `articles_tags` ON `tags`.`id` = `articles_tags`.`tag_id` WHERE `articles_tags`.`article_id` = 1
=> #<ActiveRecord::Associations::CollectionProxy [#<Tag id: 1, name: nil, description: nil, created_at: "2016-04-04 05:05:54", updated_at: "2016-04-04 05:05:54", article_id: nil>]>

出たエラー

マイグレーションファイルでの関連付けを忘れていて以下のエラーが出ました

irb(main):008:0* Article.first.tags
  Article Load (0.9ms)  SELECT  `articles`.* FROM `articles`  ORDER BY `articles`.`id` ASC LIMIT 1
Mysql2::Error: Table 'development.articles_tags' doesn't exist: SHOW FULL FIELDS FROM `articles_tags`
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'development.articles_tags' doesn't exist: SHOW FULL FIELDS FROM `articles_tags`