2 flat logo on transparent 256
2018-01-14

【初心者・独学者向け】Ruby On Railsで中間テーブルを作成し、多対多を実現する

140986 osx7pe 443 iloveimg compressed

Ruby On Railsの中間テーブルを利用して多対多の関係を実現する方法を記載します。

多対多で何ができるか?

1記事に関連するカテゴリーを複数持たせたり、 ツイッターのツイートに対して、複数のタグを持たせたり などなどです。

多対多の関係とは?

記事から見るとカテゴリーを複数持っているので、記事に対して、カテゴリーは多になります。

カテゴリーから見ると1カテゴリーに複数の記事が関連しているので、カテゴリーから見ると記事は多になります。 この関係が多対多になります。

中間テーブルとは?

多対多の関係は2つのモデルでは実現出来ないため、 中間テーブルを利用し多対多の関係を実現します。

以下に3つのサンプルテーブルを記載しています。

articleテーブル(記事を投稿するテーブル)

article_id タイトル
2 RubyOnRailsに関する記事
3 Javaに関する記事

categoryテーブル(記事カテゴリーのテーブル)

category_id タイトル
1 プログラミング全般
2 RubyOnRails
3 Java

category_articleのテーブル(中間テーブル)

category_id article_id
1 2
2 2
1 3
3 3

上記の用にcategory_articleテーブルでcategoryとarticleの関係を 紐付け、多対多の関係を実現します。

上記の例題では、「RubyOnRailsに関する記事」を表示すると それの記事のカテゴリーは 「プログラミング全般」と「RubyOnRails」 のカテゴリーが表示されます。

Modelのアソシエーションの関連性設定

マイグレーションファイルは以下の様に記載して、マイグレーションを実行します。

class CreateCategoriesArticles < ActiveRecord::Migration
  def change
    create_table :categories_articles do |t|
      t.integer  :category_id
      t.integer  :article_id
      t.timestamps null: false
    end
  end
end

その後は中間テーブルのModel(CategoriesArticleModel)を設定します。

CategoriesArticleModelでArticleのModelとCategoryのModelを関連付けます。

class CategoriesArticle < ActiveRecord::Base
  belongs_to :category
  belongs_to :article
end

次はArticleModelの設定です。

ArticleModel

class Article < ActiveRecord::Base

  has_many :categories_articles
  has_many :categories, through: :articles_categories

end

中間テーブルを通して繋がっているものには through: :articles_categoriesというkeyをつけます。

throughオプションによりarticles経由でcategoryにアクセスできるようになります。

上記設定で、articles_categories.categoriesで記事に関連するカテゴリーを取得できます。

次はCategoryModelの設定です。

Category.model

class Category < ActiveRecord::Base
  has_many :categories_articles
  has_many :articles, through: :categories_articles
end

Articleと同様にthrough: :categories_articlesというkeyをつけます。

これもcategories_articles.articlesで、カテゴリーに属する記事へアクセス可能になります。

Modelの設定は以上になります。

viewでの呼び出し方

記事に紐づくカテゴリーを呼び出すには、 Article.modelに設定したキーarticles_categoriesを利用し 呼び出します。

ArticlesController 

  def show
    @article = Article.find(params[:id])
  end

show.html

- @article.articles_categories.each do |article_categories|
  = article_categories.category.name

新規記事投稿時にカテゴリーを紐付ける

newアクションで@article.categories_articles.buildとすると articleに紐づく中間テーブルのインスタンスが精製される

その後create アクションのストロングパラメーターで category_idsを受け取って登録処理が行われます。

ArticlesController 

  def new
    @article = Article.new
    @article.articles_categories.build
  end

  def create
    @article = Article.new(article_params)

    if @article.save
      redirect_to dashboards_path
    else
      render 'new'
    end
  end

  def article_params
    params.require(:article).permit(:title, :content, { :category_ids=> [] })
  end

下記フォームでは1記事に対して複数のカテゴリーを設定できるようにしています。

その為、collectioncheckboxesで複数選択できるようにしています。

また引数の項目はcategory_idsと複数形にし、controllerのストロングパラメーターで受け取ります。

new.html

= simple_form_for @article do |f|
  = f.input :title
  = f.collection_check_boxes :category_ids, Category.all, :id, :name

以上になります

その他の関連記事

Ruby On Rails でデータを取得するメソッド一覧

Ruby On Railsのscopeメソッドで検索を効率化する

Sequel PROでAWSのDBに接続する

【初心者・独学者向け】Ruby On RailsでテーブルやModelを削除する際のコマンド

Ruby On Rails4で簡易ブログを作成する1 | VIew Controller ルートを作成する

Ruby On RailsでRedisを利用してランキング機能を実装する

Ruby On Railsとtwitterの投稿機能を連携する

前の記事
次の記事