Reputation: 533
I am working on a rails app and making a nested resource for pictures. The model is Picture
, and it is polymorphic and interacts with a couple different tables.
I am working on the controller action, and the create method. According to this answer and other things I have seen with paperclip, the params should follow the format of table_name
and then file
. Even when doing that, I am still getting a param is missing or the value is empty: picture
error.
Here is my code:
Picture.rb
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
has_attached_file :image, style: { small: '64x64', medium: '100x100', large: '200x200' }
validates_attachment :image, presence: true, content_type: { content_type: /\Aimage\/.*\Z/ },
size: { in: 0..5.megabytes }, default_url: 'missing_img.png'
acts_as_list scope: [:imageable_id, :imageable_type]
end
pictures_controller.rb
class PicturesController < ApplicationController
before_action :authorize_user!
before_action :set_resource!
def index
@pictures = @resource.pictures
end
def create
@picture = @resource.pictures.new(picture_params) do |pic|
pic.imageable_type = @resource
pic.imageable_id = @resource.id
end
if @picture.save
redirect_to :back
flash[:success] = 'Image Saved!'
else
redirect_to :back
flash[:danger] = "#{@picture.errors.full_messages.to_sentence}"
end
end
def destroy
@picture = Picture.find(params[:id])
@resource.pictures.delete(@picture)
redirect_to :back
flash[:success] = "Picture deleted"
end
private
def set_resource!
klass = [Gym, User, Location, Product].detect { |c| params["#{c.name.underscore}_id"] }
@resource = klass.find(params["#{klass.name.underscore}_id"])
end
def picture_params
params.require(:picture).permit(:image)
end
end
pictures/index.html
<h6>Upload Pictures</h6>
<%= form_for(current_user, url: url_for(controller: 'pictures', action: 'create'), method: :post, html: { multipart: true, class: 'form-horizontal' }) do |f| %>
<%= f.file_field :image, type: :file, multiple: true, style: 'padding-bottom: 25px;' %>
<%= f.submit "Upload", class: "btn btn-gen" %>
<% end %>
And here is the param request on form submit:
{"utf8"=>"✓",
"authenticity_token"=>"+fsA6liECF7pkUp/0BA0wDHq9Vv63jB+WBb7O/uUEDhhmIOZ22Rb1rNWDwuwPTDPNS7jg7vP/fVCVllDV21wDw==",
"user"=>{"image"=>[#<ActionDispatch::Http::UploadedFile:0x007f87b138acf8 @tempfile=#<Tempfile:/var/folders/9c/1_0mk00n297f560_fpv9jzl40000gn/T/RackMultipart20161020-25582-3qt3gc.jpg>,
@original_filename="b4lROOR.jpg",
@content_type="image/jpeg",
@headers="Content-Disposition: form-data; name=\"user[image][]\"; filename=\"b4lROOR.jpg\"\r\nContent-Type: image/jpeg\r\n">]},
"commit"=>"Upload",
"user_id"=>"15"}
Even with this, I am still getting the error. Does anyone see anything wrong I'm doing in my code that I could fix? Any help is much appreciated.
Upvotes: 0
Views: 158
Reputation: 533
I figured out a temporary work around. Definitely not ideal, and if anyone has a better suggestion I would love to hear it. But here is what I currently have that does work.
def create
pic = nil
if params[:user]['image']
params[:user]['image'].each do |image|
pic = @resource.pictures.create(image: image, imageable_type: @resource, imageable_id: @resource.id)
end
if pic.save
redirect_to :back
flash[:success] = 'Image Saved!'
else
redirect_to :back
flash[:danger] = "#{pic.errors.full_messages.to_sentence}"
end
else
flash[:danger] = "Picture file not found"
redirect_to :back
end
end
Upvotes: 0
Reputation: 102134
The problem is that your picture_params
method requires the route param key picture
while your form has the key user
.
Lets do some refactoring:
private
def set_resource!
@resource = resource_class.find(params[param_key + "_id"])
end
def resource_class
@resource_class ||= [Gym, User, Location, Product].detect do |c|
params[ param_key(c) + "_id" ]
end
end
def param_key(klass = resource_class)
ActiveModel::Naming.param_key(klass)
end
def picture_params
params.require(param_key).permit(:image)
end
Instead of klass.name.underscore
we use ActiveModel::Naming
which is how rails figures out how to use models for stuff like routes, params or translations.
Upvotes: 1