テーブル間の関連(リレーション)がある場合の登録処理

RSSを生成するWebアプリケーションで、以下のような関連があるとする。

Channel:1 -> Item:N

この場合のスキーマとモデルクラスは以下のようになる。

  • db/schema.rb
  create_table "channels", :force => true do |t|
    t.column "about",       :string, :limit => 128, :default => "", :null => false
    t.column "title",       :string, :limit => 32,  :default => "", :null => false
    t.column "link",        :string, :limit => 128, :default => "", :null => false
    t.column "description", :string, :limit => 64,  :default => "", :null => false
  end

  create_table "items", :force => true do |t|
    # 外部キー名を(モデル名)_idにすること
    t.column "channel_id",  :integer,                :default => 0,  :null => false
    t.column "title",       :string,   :limit => 64, :default => "", :null => false
    t.column "description", :text,                   :default => "", :null => false
    t.column "date",        :datetime,                               :null => false
  end
  • app/models/channel.rb
class Channel < ActiveRecord::Base
  has_many :items
end
  • app/models/item.rb
class Item < ActiveRecord::Base
  belongs_to :channel
end
  • app/controllers/ItemsController
  def create
    @item = Item.new(params[:item])
    #以下の2行でデータが関連付けられる。
    #これをやらないとitem.channel_idが初期値のままになる。
    @channel = Channel.find(params[:channel_id])
    @channel.items << @item
    if @item.save
      flash[:notice] = 'Item was successfully created.'
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
  end