2 flat logo on transparent 256
2018-01-14

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

140986 osx7pe 443 iloveimg compressed

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

多対多で何ができるか?

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

多対多の関係とは?

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

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

ここまでで、あまり理解出来ない方は この記事の上部へスクロールして、パンくずリストをご覧ください。

以下のようなパンくずリストがあり、こちらにマウスを当てると記事カテゴリーへのリンクとなっていますが

パンくずリスト

現在ご覧になっているこの記事に対して、Ruby on Railsや初心者向けというような複数のカテゴリーが設定されています。

また、パンくずリストのRuby on Railsのカテゴリーを選択すると複数の記事が表示されます、

つまりRuby on Railsのカテゴリーに複数の記事が設定されています。

これが多対多の関係になります。

なおデータベース自体の概要が分からない方は以下から 【初心者・独学者向け】データベースとは何かを解説します

中間テーブルとは?

多対多の関係は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

上記の用にcategoryarticleテーブルでcategoryidとarticle_idを レコードで紐付け、多対多の関係を実現します。

上記の例題では、「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

1記事に対して複数のカテゴリーを設定しているので、 viewで値を表示する際は繰り返し処理で呼び出しを行わないとエラーになります

※値を取得できなかった場合の処理も記載する必要がありますが、こちらは割愛しております。

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

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の投稿機能を連携する

Rubyでサイトをスクレイピングし、ローカルに画像を保存する

前の記事
次の記事