I'm trying to wrap my head around using polymorphic associations to make file management less repetitive in a simple rails app. I'm using carrierwave to handle the file uploading. Here's what I have so far:
app/uploaders/file_uploader.rb
class FileUploader < CarrierWave::Uploader::Base
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
app/models/attachment.rb
class Attachment < ActiveRecord::Base
mount_uploader :file, FileUploader
belongs_to :attachable, polymorphic: true
end
app/models/photo.rb
class Photo < ActiveRecord::Base
attr_accessible :caption, :attachment
has_one :attachment, as: :attachable
end
I can handle this fine in the rails console:
$ rails console
> photo = Photo.new
> attachment = Attachment.new
> attachment.file = File.open('tmp/demo.png')
> photo.attachment = attachment
> photo.save
> photo.attachment
=> #<Attachment id: 3, file: "demo.png", attachable_id: 5, attachable_type: "Photo", created_at: "2013-04-13 16:56:31", updated_at: "2013-04-13 16:56:31">
So my problem is really in the photos controller:
ActiveRecord::AssociationTypeMismatch in PhotosController#create
Attachment(#70310274945400) expected, got ActionDispatch::Http::UploadedFile(#70310271741380)`
Any help on this is hugely appreciated. I might not have the greatest grasp of polymorphic associations.
UPDATE
Taking @manoj's suggestion, I edited the photo form to nest the attachment:
<%= f.fields_for :attachment do |attachment_f| %>
<%= attachment_f.file_field :file %>
<% end %>
I'm now getting this error when I attempt to submit the form:
ActiveRecord::AssociationTypeMismatch (Attachment(#70135925415240) expected, got ActiveSupport::HashWithIndifferentAccess(#70135923190420)):
app/controllers/photos_controller.rb:43:in 'new'
app/controllers/photos_controller.rb:43:in 'create'
The post params should be something like this
params => { "photo" =>
{ :attachment_attribute =>
{:file => ActionDispatch::Http::UploadedFile}
}
}
but your post param most probably is
params => { "photo" => { :attachment => ActionDispatch::Http::UploadedFile}}
Your view should contain fields_for to handle the nesting in models. You have to create a file field for the attribute "file" of the Attachment model
<%=form_for @photo do |photo_f|%>
....
<%=photo_f.fields_for :attachment do |attachment_f|%>
<%= attachment_f.file_field :file%>
<%end%>
....
<%end%>
UPDATE
<%=photo_f.fields_for :attachment_attributes do |attachment_f|%>
And in the photo model add these,
accepts_nested_attributes_for :attachment
attr_accessible ..., :attachment_attributes