ページ

2012年5月8日

ActiveRecord::AssociationTypeMismatch errorの対策

Ruby on Rails ロゴ
外部キーのあるモデルのビュー周りで、ActiveRecord::AssociationTypeMismatch errorが発生した。書籍やWebで調べてもぴったり同じ解決法がなかったので、記事として残しておく。

今回実装したかった機能は、外部キーを持つReportsに対してCreate, Read, Updateの機能を実装すること。

難しい実装じゃないはずなんだけど、Railsに慣れていなかったせいか苦労した。これからもっと勉強して実装経験を積んでいかないと、自分のRailsのレベルは実戦には程遠いだろうと感じた。

バージョン

  • ruby 1.9.3
  • rails 3.2.2

データベース定義

ReportsテーブルとSubmittersテーブルがあり、以下のように定義されているとする。

テーブル名Submitters
物理名データ型NullDefault備考
idintegerNoPRIMARY KEY
AUTO INCREMENT
namestringYesNull
created_atdateNo
updated_atdateNo

テーブル名Reports
物理名データ型NullDefault備考
idintegerNoPRIMARY KEY
AUTO INCREMENT
titlestringYesNull
submitter_idreferencesYesNullFOREIGN KEY
created_atdateNo
updated_atdateNo


Create & Update

とりあえずコードから。

reports_controller.rb (抜粋)
def new
  @report = Report.new
  @submitter = Submitter.all

  respond_to do |format|
    format.html
  end
end

def edit
  @report = Report.find(params[:id])
  @submitter = Submitter.all
end

def create
  @report = Report.new(params[:report])

  respond_to do |format|
    if @report.save
      format.html { redirect_to @report, notice: 'Report was successfully created.' }
    else
      format.html { render action: "new" }
    end
  end
end

def update
  @report = Report.find(params[:id])

  respond_to do |format|
    if @report.update_attributes(params[:report])
      format.html { redirect_to @report, notice: 'Report was successfully updated.' }
    else
      format.html { render action: "edit" }
    end
  end
end


_form.html.rb
<%= form_for(@report) do |f| %>
  <% if @report.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@report.errors.count, "error") %> prohibited this report from being saved:</h2>
      <ul>
        <% @report.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </div>

  <div class="field">
    <%= f.label :submitter %></div>
    <%= f.collection_select( :submitter_id, @submitter, :id, :name ) %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>


new.html.erb
<h1>New report</h1>

<%= render 'form' %>

<%= link_to 'Back', reports_path %>


edit.html.erb
<h1>Editing report</h1>

<%= render 'form' %>

<%= link_to 'Show', @report %> |
<%= link_to 'Back', reports_path %>

Read

とりあえずコードから。

reports_controller.rb (抜粋)
def index
  @reports = Report.all

  respond_to do |format|
    format.html # index.html.erb
  end
end

def show
  @report = Report.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
  end
end


index.html.erb
<h1>Listing reports</h1>

<table>
  <tr>
    <th>タイトル</th>
    <th>提出者</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @reports.each do |report| %>
  <tr>
    <td><%= report.title %></td>
    <td><%= report.submitter.name if report.submitter %></td>
    <td><%= link_to 'Show', report %></td>
    <td><%= link_to 'Edit', edit_report_path(report) %></td>
    <td><%= link_to 'Destroy', report, confirm: 'Are you sure?', method: :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Report', new_report_path %>


show.html.erb
<p id="notice"><%= notice %></p>

<p>
  <b>Title:</b>
  <%= @report.title %>
</p>

<p>
  <b>Submitter:</b>
  <%= @report.submitter.name %>
</p>


<%= link_to 'Edit', edit_report_path(@report) %> |
<%= link_to 'Back', reports_path %>



解説

後で書く。

まとめ

…。
Related Posts Plugin for WordPress, Blogger...