モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)

テーブルアソシエーション (Rails4)

モーダルを閉じる

ステッカーを選択してください

モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

公開日公開日
2014/08/25
最終更新最終更新
2021/10/07
記事区分記事区分
一般公開

目次

    推しはTypeScript

    0
    ステッカーを贈るとは?

    モデル間に従属関係がある場合、モデルにアソシエーションを記述して関係性を明示しておくことで、テーブルをjoinするSQLをRailsのActiveRecordが自動的に裏で実行してくれるようになり、直感的な情報アクセスが可能になります。

    belongs_to

    usersテーブル

    commentsテーブル

    • 「user_id」を外部キーとして持っている
    • "A comment belongs to a user."

    app/models/comment_model.rb

    class CommentModel < ActiveRecord::Base
      belongs_to :user # ←単数形
    end
    

    has_many

    belongs_to とは逆の概念です。主従関係は同じであり、テーブル構成も同じです。以下のようなメソッドが使用できるようになります。

    • @user.comments
    • @user.comments.size
    • @user.comments.empty?
    • @user.comments.find(1) # id=1
    • @user.comments.exist?(1) # id=1
    • @user.comments.destroy(@comment)
    • @user.comments.clear # すべて削除
    • @user.comments<<@comment # ユーザのコメントを追加
    • @user.comments = @new_comments # ユーザのコメントを一括登録
    • @comment = @user.comments.build(title: 'Abc') # 保存しない。「@comment.save」と続ける
    • @user.comments.create(title: 'Abc') # 保存する

    usersテーブル

    • "A user has many comments."

    app/models/user_model.rb

    class UserModel < ActiveRecord::Base
      has_many :comments # ←複数形
    end
    

    commentsテーブル

    • 「user_id」を外部キーとして持っている

    has_one

    belongs_to の特殊な場合における逆の概念です。主従関係は同じであり、テーブル構成も同じです。特殊な場合とは、異なる二つのものが、同じものにbelongしないことが保証されている場合のことを差します。以下のようなメソッドが使用できるようになります。

    • @user.comment = @comment # あるユーザのcommentとして@commentを登録 (commentのuser_idにuserのidを設定)
    • @comment = @user.build_comment(title: 'Abc') # commentを作成し、そのuser_idに@userのidを設定) (保存しない @comment.saveと続く)
    • @user.create_comment(title: 'Abc') # commentを作成し、そのuser_idに@userのidを設定) (保存する)

    usersテーブル

    • "A user has one comment."

    app/models/user_model.rb

    class UserModel < ActiveRecord::Base
      has_one :comment # ←単数形
    end
    

    commentsテーブル

    • 「user_id」を外部キーとして持っている

    「has_one」と「belongs_to」の関係において、どちらのテーブルに外部キーを持たせるかは、それらの主従関係を考えて決定します。「has_one」する側は他方を必要としません。「belongs_to」する側は自分が存在のために他方を必要とします。

    has_and_belongs_to_many

    多対多の場合です。主従関係はありません。中間テーブルが必要となります。中間テーブルの名称は、参照先テーブルを辞書順にアンダーバー '_' でつなげたものとします。中間テーブルに独自の情報列は作成せず、したがって対応するモデルも不要です。HBTMとも称します。以下のようなメソッドが使用できるようになります。

    • @user.comments
    • @user.comments.size
    • @user.comments.empty?
    • @user.comments.find(1) # id=1
    • @user.comments.exist?(1) # id=1
    • @user.comments.destroy(@comment)
    • @user.comments.clear # すべて削除
    • @user.comments<<@comment # ユーザのコメントを追加
    • @user.comments = @new_comments # ユーザのコメントを一括登録
    • @comment = @user.comments.build(title: 'Abc') # 保存しない。「@comment.save」と続ける
    • @user.comments.create(title: 'Abc') # 保存する

    authorsテーブル

    app/models/author_model.rb

    class AuthorModel < ActiveRecord::Base
      has_and_belongs_to_many :books
    end
    

    booksテーブル

    app/models/book_model.rb

    class BookModel < ActiveRecord::Base
      has_and_belongs_to_many :authors
    end
    

    authors_booksテーブル

    • 「author_id」および「book_id」を列として持ちます

    has_many through

    「has_and_belongs_to_many」において、中間テーブル自体は情報を有さず、したがってモデルも存在しませんでした。そうではなく、情報を有する存在意義のあるモデルが中間となり、二つのモデルに「has_and_belongs_to_many」の関係を与える場合は「has_many through」を使用します。

    usersテーブル

    app/models/user_model.rb

    class UserModel < ActiveRecord::Base
      has_many :reviews
      has_many :books, through: :reviews
    end
    

    reviewsテーブル

    app/models/review_model.rb

    class ReviewModel < ActiveRecord::Base
      belongs_to :user
      belongs_to :book
    end
    

    booksテーブル

    app/models/book_model.rb

    class BookModel < ActiveRecord::Base
      has_many :reviews
      has_many :users, through: :reviews
    end
    

    カウンターキャッシュ

    has_manyしている個数を列として管理する機能です。belongs_toしている側のテーブルにレコードが追加または削除される度に、belongs_toされている側のhas_manyの個数を管理する列を自動で更新する機能です。「.size」メソッドを実行する際に、SQLを実行する必要がなくなり高速化できます。「.length」および「.count」ではなく「.size」です。

    usersテーブル

    • "A user has many comments."

    app/models/user_model.rb

    class UserModel < ActiveRecord::Base
      has_many :comments # ←複数形
    end
    
    • 「comments_count」というInteger型の列を用意しておきます

    db/migrate/20140617113217_create_user_models.rb

    t.integer :reviews_count, default: 0
    

    commentsテーブル

    • 「user_id」を外部キーとして持っている

    app/models/comment_model.rb

    class CommentModel < ActiveRecord::Base
      belongs_to :user, counter_cache: true
    end
    

    DBへのデータアクセスを減らす (includes)

    例えば、@user.commentsをeachするとDBへのデータアクセスが複数回数発生して非効率です。そこで

    @users = User.includes(:comments).all
    

    などとすると、@user.commentsのeachではすでにメモリにある情報にアクセスするだけになり高速化できます。公式ドキュメントはこちらです。

    0
    詳細設定を開く/閉じる
    アカウント プロフィール画像 (本文下)

    推しはTypeScript

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    さらに詳しく →
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      関連記事

      • レイアウトおよび部分テンプレートに関するまとめ (Rails4)
        レイアウトおよび部分テンプレートはどちらもテンプレート (*.html.erb) に共通の要素をまとめておき、任意のテンプレートから利用できるようにしておくための仕組みです。フッターやヘッダーといった大枠はレイアウト、小さなパーツは部分テンプレートというイメージで使い分けましょう。 レイアウトの使用方法 クラス毎に指定する方法と、アクション毎に指定する方法があります。 app/views/layo...
        taro三世taro三世10/21/2016に更新
        いいねアイコン画像0
      • Ruby コードスニペット (正規表現)
        sample.rb str = "001: This is a string." var1,var2 = 2,3 # 'EOS'とすると#{}による変数展開がなされない (%03dは展開される) doc = (<<"EOS" % var1) # 括弧は省略可。要は<<"EOS"の次の行からEOSまで。(参: <<-"EOS"とすると前に空白...
        だいふくうさぎだいふくうさぎ5/13/2018に更新
        いいねアイコン画像0
      • OAuthを用いずにTwitterに自動投稿する (回数制限あり, Selenium with Ruby)
        Seleniumを用いて、OAuthを用いずにTwitterに自動投稿するRubyスクリプトを記述してみます。連続で複数回実行すると、ボット判定としてキャプチャ認証が発生します。その認証までは通過できませんので悪しからず。また、Twitterの仕様変更次第ではDOMの構造が変化するため、下記サンプルは機能しなくなる恐れが有ります。 twitter_post.rb #!/usr/bin/ruby r...
      • Ruby における日本語のエンコーディング
        日本語を含めて多言語対応する際には、Asciiコード以外の文字コードセットが必要になります。日本語が主となる場合、よく使われる文字セットにはUnicode, Shift_JIS, EUC-JPがあります。このうち Unicode だけは特殊であり、世界中のあらゆる文字を収録しようとしていることから 1 文字を表現するために必要なバイト数が大きくなってしまっています。そのため Unicode のうち...
        だいふくうさぎだいふくうさぎ4/21/2017に更新
        いいねアイコン画像0
      • Rails3ビューテンプレートの基本的な使用方法 (Ruby)
        Railsでは、ERB (eRuby (テキストファイルにRubyスクリプトを埋込む書式の仕様) をRubyで実装したもの) を用いてHTML内にRubyスクリプトを埋込むことができます。 <% %> で囲むと出力されません (if-elseなど制御構文を記述します) <%= %> で囲むとエスケープ出力されます <%== %> で囲むとエスケープされずに...
        ほんわかパンダほんわかパンダ10/21/2016に更新
        いいねアイコン画像0