91

私はhas_and_belongs_to_many関係を実行したい2つのモデルrestaurantuserを持っています。Rails has_and_belongs_to_many migration

私はすでにモデルファイルに入ったと私はRailsの3とのような何かを行うことができるはず、この時点で想定しhas_and_belongs_to_many :restaurantshas_and_belongs_to_many :users

追加しました:

rails generate migration .... 

が、私が持っているすべてのものを試してみると失敗するようです。私はこれが本当にシンプルなものだと確信しています。

答えて

193

restaurant_iduser_id(主キーなし)のみの別の結合テーブルを追加する必要があります。アルファベット順です。

まず、移行を実行してから、生成された移行ファイルを編集します。

レール3

rails g migration create_restaurants_users_table 

レール4

rails g migration create_restaurants_users 

レールから5

rails g migration CreateJoinTableRestaurantUser restaurants users 

0:

JoinTable は、名前の一部である場合テーブルを結合生み出す発電機もあります:


あなたの移行ファイル(:id => falseに注意してくださいが。それは)主キーの作成を防ぐものです:

Railsの3

class CreateRestaurantsUsers < ActiveRecord::Migration 
    def self.up 
    create_table :restaurants_users, :id => false do |t| 
     t.references :restaurant 
     t.references :user 
    end 
    add_index :restaurants_users, [:restaurant_id, :user_id] 
    add_index :restaurants_users, :user_id 
    end 

    def self.down 
    drop_table :restaurants_users 
    end 
end 

Railsの4

class CreateRestaurantsUsers < ActiveRecord::Migration 
    def change 
    create_table :restaurants_users, id: false do |t| 
     t.belongs_to :restaurant 
     t.belongs_to :user 
    end 
    end 
end 

t.belongs_toは、自動的に必要なインデックスを作成します。 def changeは、フォワードまたはロールバックの移行を自動的に検出します。アップ/ダウンの必要はありません。

Railsの5

create_join_table :restaurants, :users do |t| 
    t.index [:restaurant_id, :user_id] 
end 

注:table_name呼ばcreate_join_tableにパラメータとして渡すことができるカスタム・テーブル名のオプションもあります。デフォルトではdocs

からは、結合テーブルの名前がアルファベット順に 、create_join_tableに提供 最初の二つの引数の和集合から来ています。テーブル名をカスタマイズするには、次のオプションを指定します。テーブル名 オプション:

+0

ソリューションが私にとって完璧に機能してくれてこの方法を使用すると単純な間違いがありました。rake db:railsコマンドの後に移行して、テーブルを生成しませんでした。 rake db:ロールバックをしてからファイルを編集し、rake db:migrateを実行しなければならなかったが、今はすべて動作する。 – dbslone

+6

@Dex - ちょうど好奇心の理由から、逆の列順序で定義された第2の複合インデックスを使用している理由を説明できますか?私は列の順序が重要ではないという印象を受けました。私はDBAではなく、自分の理解をさらに進めたいと思っています。ありがとう! – plainjimbo

+9

@ジンバあなたはそれを必要としません、それは本当にあなたのクエリに依存します。インデックスは左から右に読み込まれるので、 'restaurant_id'で検索すると、最初のインデックスが最も速くなります。 'user_id'で検索している場合は、2番目の方法が役に立ちます。もしあなたが両方で検索しているのであれば、データベースが必要なだけのスマートなものになると思います。だから私は第二のものが実際に複合化される必要はないと思う。これはほんの一例に過ぎません。これはRailsの質問だったので、DBセクションに投稿するとより完全な答えが得られます。 – Dex

6

HABTM関係の場合は、結合テーブルを作成する必要があります。結合テーブルのみがあり、そのテーブルにはidカラムがありません。この移行を試してください。

def self.up 
    create_table :restaurants_users, :id => false do |t| 
    t.integer :restaurant_id 
    t.integer :user_id 
    end 
end 

def self.down 
    drop_table :restaurants_users 
end 

結合テーブルを作成するときにthis relationship rails guide tutorials

+0

私はあなたがモデルを必要としないと思うし、HABTM関係のモデルが必要であるというリンクには何も表示されません。 –

+1

生成されたクエリを高速化するには、idフィールドにインデックスを追加します。 –

24

をチェックする必要があり、2つのテーブルの移行名/クラスのアルファベット順に記載されていることが必要要件に細心の注意を払います。モデル名が類似している場合、これは簡単にあなたを噛んでしまう可能性があります。 "abc"と "abb"。期待どおり

rails g migration create_abc_abb_table 

あなたの関係を実行した場合でしょうないが仕事。代わりに

rails g migration create_abb_abc_table 

を使用する必要があります。

+0

どちらが先ですか? fooまたはfoo_bar? –

+1

@BSeven私は、どのようなUNIXソートでもあなたに伝えます。 – shacker

+0

レールコンソールでのラン:["foo_bar"、 "foo"、 "foo bar"] sort#=> ["foo"、 "foo bar"、 "foo_bar"] Unixソートは同じです。 – Shadoath

23

ここの回答はかなり古いです。 Rails 4.0.2以降、移行ではcreate_join_tableが使用されています。

rails g migration CreateJoinTableRestaurantsUsers restaurant user 

これは以下を生成します:実行し、移行を作成するには

class CreateJoinTableRestaurantsUsers < ActiveRecord::Migration 
    def change 
    create_join_table :restaurants, :users do |t| 
     # t.index [:restaurant_id, :user_id] 
     # t.index [:user_id, :restaurant_id] 
    end 
    end 
end 

インデックスを作成する場合は、これらの列は、それぞれの行のコメントを解除し、あなたが行ってもいいです!

関連する問題