動かざることバグの如し

3分経てば忘れそうなことをメモします

Railsで1対多を実現

サイトによってバラバラだしまとめないと死ぬ

準備

customerモデルとorderモデルを作って紐付けたい

Customerモデルの作成

rails g model Customer name:string

Orderモデルの作成

rails g model Order order_date:date

マイグレーション

rake db:migrate

当然ながら以下が生成される

class CreateCustomers < ActiveRecord::Migration
  def change
    create_table :customers do |t|
      t.string :name

      t.timestamps null: false
    end
  end
end
class CreateOrders < ActiveRecord::Migration
  def change
    create_table :orders do |t|
      t.date :order_date

      t.timestamps null: false
    end
  end
end

1対多のためのマイグレーションファイルを作成

1つの「customer」に対して多数の「order」がつくので

rails g migration AddCustomerRefToOrder customer:references

すると以下のマイグレーションファイルが生成される

ちゃんとドキュメント読もうね

class AddCustomerRefToOrder < ActiveRecord::Migration
  def change
    add_reference :orders, :customer, index: true, foreign_key: true
  end
end

これでrake db:migrateこれで

モデルに1対多の宣言を追加

order.rbbelongs_toを追加

class Order < ActiveRecord::Base
    belongs_to :customer
end

customer.rbhas_manyを追加 orders複数なので注意

class Customer < ActiveRecord::Base
    has_many :orders
end

実際に使ってみる

客追加

c = Customer.create name:"taro"
 => #<Customer id: 3, name: "taro", created_at: "2015-10-13 07:36:13", updated_at: "2015-10-13 07:36:13"> 

客に対してオーダーを追加

c.orders << Order.create(order_date: Time.now)
 => #<ActiveRecord::Associations::CollectionProxy [#<Order id: 6, order_date: "2015-10-13", created_at: "2015-10-13 07:38:34", updated_at: "2015-10-13 07:38:34", customer_id: 3>]> 

オーダーの参照

c.orders
 => #<ActiveRecord::Associations::CollectionProxy [#<Order id: 6, order_date: "2015-10-13", created_at: "2015-10-13 07:38:34", updated_at: "2015-10-13 07:38:34", customer_id: 3>]> 

c.ordersは配列のように扱える

c.orders.count
 => 1

c.orders.first
 => #<Order id: 6, order_date: "2015-10-13", created_at: "2015-10-13 07:38:34", updated_at: "2015-10-13 07:38:34", customer_id: 3> 

オーダーから見てみる

Order.last
 => #<Order id: 6, order_date: "2015-10-13", created_at: "2015-10-13 07:38:34", updated_at: "2015-10-13 07:38:34", customer_id: 3>

Order.last.customer
 => #<Customer id: 3, name: "taro", created_at: "2015-10-13 07:36:13", updated_at: "2015-10-13 07:36:13">
広告を非表示にする