QA@IT

form_forで画像等のモデルに直接関係のない値を送るときにはどうすればいいのか?

3692 PV

現在、Rails4.0で開発をしているのですが、form_forを使ったデータ入力画面で、form_for内で画像のような直接モデルのカラムと関係のないデータを、どのようにモデルと結びつければいいのかわからず、質問させていただきました。

もう少し具体的に例を挙げて説明させていただきます。実際はこの通りにはやっていないのでへんな記述があったらすいません。

ブログシステムを作っているとします。
このブログのカラムには「title」と「img_url」があるとします。
このブログは、ブログ毎にサムネイル画像が設定できます。この画像はブログのidを元にしたURL先(例:blog/[:id]/thumbanail.png)にアップロードして、そのURLをimg_urlに入れる事で参照できるようになります。

なので、タイトルとサムネイル画像をアップするために以下の様なフォームを書きました。

<%= form_for @blog do |f| %> 
  タイトル<br>
  <%= f.text_field :title %><br>
  <br>
  サムネイル画像<br>
  <%= f.file_field :img %><br>
<% end %>

コントローラではこんな感じです。(permitは今は気にしません)

@blog = Blog.new(params[:blog])
@blog.save!
@blog.upload_img(params[:img]) ##自作関数

しかしこうすると、newする時点で

ActiveRecord::UnknownAttributeError: unknown attribute: img

というエラーが出ると思います。
なぜならimgというカラムは存在しないからです。

この問題をどう解決すればいいのでしょうか?というのが今回の質問です。

一応私が考えた解決策はいくつかあります。しかしながらどれもよくありません。

1つは、

<%= file_field_tag :img %><br>

こんな感じにイメージだけタグを使って書いてしまう方法です。

ですがこれには問題があります。それは複数のモデルをまとめて、form_forで送信する場合に、見分けがつかなくなることです。
今まで問題を複雑にしないためにかいていなかったのですが、
画像を入れたいモデルは多体1の関係にあり、1つのフォームに複数のblogがいる感じになります。
それを「accepts_nested_attributes_for」を使って、newで一気に関連先まで流し込むのですが、その際に後から画像データを入れようにも、既に関連先に複数のモデルがnewされた後なので、この画像データは複数あるモデルのどれに対応するのか見分けがつかないのです。

2つ目は、

あきらめてform_tagで全部書く事です。そしてnew(:title => params[:title])みたいに書いていきます。
しかしながらこれだと、カラムが増えたときにnewの引数がどんどん長くなっていきます。

なにか気づいた点がありましたら、ご回答いただけると幸いです。よろしくお願いします。

回答

このrailscastのように、img用のメソッドを実装されるのはどうでしょうか。

http://railscasts.com/episodes/16-virtual-attributes?view=asciicast

ruby 1.9.3 rails 3.2でしたら以下は動作しました。

class Blog < ActiveRecorde::Base
  def img
    return @img
  end
  def img=(file)
    @img = file
  end
~以下略~

こうするとコントローラは以下のようにできると思います。

@blog = Blog.new(params[:blog])
@blog.save!
@blog.upload_img(@blog.img) ##自作関数
編集 履歴 (1)
  • 返事おくれてすまいすみません。
    なるほどsetterを使えばよかったんですね。盲点でした。
    おかげさまで解決できました、ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。