I have the following code:
class User < ActiveRecord::Base
has_one :profile_image, :as => :owner, :class_name => 'Image'
has_one :cover_image, :as => :owner, :class_name => 'Image'
end
and:
class Image < ActiveRecord::Base
belongs_to :owner, polymorphic: true
end
Now I am trying to build a form where a user can update his/her images, and his/her e-mail. I am building the form like this:
= form_for @user, :url => pages_upload_path, :html => { :multipart => true } do |form|
= form.text_field :email
= form.fields_for :profile_image_attributes do |profile_image|
= profile_image.file_field :file
= form.fields_for :cover_image_attributes do |cover_image|
= cover_image.file_field :file
= submit_tag("Upload")
This however compiles to the following params hash:
[2] pry(#<PagesController>)> params[:user]
=> {"email"=>"kasper@example.com",
"profile_image"=>
{"file"=>
#<ActionDispatch::Http::UploadedFile:0x007f8a41365d30
@content_type="image/png",
@headers=
"Content-Disposition: form-data; name=\"user[profile_image][file]\"; filename=\"Screenshot 2014-04-27 02.57.34.png\"\r\nContent-Type: image/png\r\n",
@original_filename="Screenshot 2014-04-27 02.57.34.png",
@tempfile=
#<File:/var/folders/_2/rgn574910638hqstf85233hh0000gn/T/RackMultipart20140518-88429-15129ld>>},
"cover_image"=>
{"file"=>
#<ActionDispatch::Http::UploadedFile:0x007f8a413653d0
@content_type="image/png",
@headers=
"Content-Disposition: form-data; name=\"user[cover_image][file]\"; filename=\"Screenshot 2014-04-27 02.57.34.png\"\r\nContent-Type: image/png\r\n",
@original_filename="Screenshot 2014-04-27 02.57.34.png",
@tempfile=
#<File:/var/folders/_2/rgn574910638hqstf85233hh0000gn/T/RackMultipart20140518-88429-1oosnc5>>}}
But when I save this, like this, I get the following error:
@user = User.last
@user.update_attributes(params.fetch(:user, {}).permit(:email, :profile_image => [:file]))
# ActiveRecord::AssociationTypeMismatch: Image(#70115863220300) expected, got
# ActionController::Parameters(#70115879244320)
# from /Users/kaspergrubbe/.rbenv/versions/2.0.0-p353/lib/ruby/gems/2.0.0/gems
# /activerecord-4.1.0/lib/active_record/associations/association.rb:216:in
# `raise_on_type_mismatch!'
How can I get it to accept my attributes for the profile_image
?
You need to add:
accepts_nested_attributes_for :profile_image
accepts_nested_attributes_for :cover_image
The error you're getting is a result of the way rails assigns attributes. For each key it calls #{key}=
method, so in your case it is trying assign hash to profile_image
.
When you add accepts_nested_attributes_for
many thing will change. Firstly, it will define profile_image_attributes=
method which expects Hash object which will be used to build or update associated object. When fields_for
noticed that this method is defined, it will update name of the field to contain _attributes
at the end, so everything will work.
Note however that fields_for will not build if there is no object associated, so you will need to build those objects in your new and edit action.