Ruby on Railsでヘッダディテール型(親子テーブル)のデータを1画面で表現、登録する。

ヘッダディテール型、ヘッダのテーブルと明細のテーブルが1つになった画面を作りたいと思います。

実装仕様(イメージ)について

ヘッダと明細が同じ画面で表示されて、それを更新するパターン

実装環境

今回の利用したRails環境は以下のとおりです。

OS:    Windows XP (そろそろ変えたい…そればっかやな…)
Ruby:  Ruby 2.0.0p247
Rails: Rails 4.0.0
* 前回の記事内容のDevise実装が出来ている事とします。

実施内容

テスト用の新規アプリを作成

$ rails new headerdetail --no-test-framework

ヘッダのモデル・ビュー・コントローラを作る(Scaffoldを利用)

$ rails generate scaffold header header_number:integer header_description:string

明細(ディテール)のモデルを作る ※明細はモデルのみで対応するビュー等は必要ない。

$ rails generate model detail detail_number:integer detail_description:string header_id:integer

DB定義を反映する

$ bundle exec rake db:migrate

モデルに親子関係を記載する。

1.ヘッダ側のファイル
ファイル:app/models/header.rb
以下の記述を追加
has_many :details
accepts_nested_attributes_for :details, allow_destroy: true

2.明細側のファイル
ファイル:app/models/detail.rb
以下の記述を追加
belongs_to :header
validates :header_id, ;detail_number, presence: true

コントローラを修正する。

ファイル:app/controllers/header_controller.rb
1. newメソッドにヘッダの行を追加(とりあえず3行)
   そのうち、手動で増やすオプションが必要だと思われるが、それは別途調べる事にする。

  def new
    @header = Header.new
    #ここから追加
    3.times{
      @header.details.build
    }
  end

2. Strong Parametersをいじる。これは資料が少なくて結構ハマったけど、明細側のファイルは :(明細モデル)_attributes => [:id, :_destroy, (要素)]となるようです。

    def header_params
        params.require(:header).permit(:header_number, :header_description,
               :details_attributes => [:id, :detail_number, :detail_description, :_destroy])
    end

ビューを修正する。明細の表示を追加

ファイル:app/views/headers/_form.html.erb
  <div class="field">
    <%= f.fields_for :details do |dtl| %>
       <%= dtl.label :detail_number %><br/>
       <%= dtl.number_field :detail_number %><br/>
       <%= dtl.label :detail_description %><br/>
       <%= dtl.text_field :detail_description %><br/>
    <% end %>
  </div>

これで、レイアウトの問題は無視して、とりあえずヘッダと明細の同時更新が可能になりました。今日は疲れたので、ここまでとします。