I'm having trouble with carrierwave and rails 4 strong parameters. I have a very simple model with a carrier wave upload button. I'd like to show an error message if someone submits the upload form without choosing a file to upload.
Right now, I get a param not found:photo
error with this message:
# Never trust parameters from the scary internet, only allow the white list through.
def photo_params
params.require(:photo).permit(:image)
end
This error is happening because Rails 4's strong parameters is requiring that the image parameter be present to submit the form, but it's not there because the user hasn't selected an image.
I can't figure out a way to work around this and have it redirect to the same action and display an error message.
Is there a way to do this with strong parameters?
Here's the development log when I try to use the form without a photo selected:
https://gist.github.com/leemcalilly/09b6166ce1af6ca6c833
And here's the development log when I choose a photo and it uploads successfully:
https://gist.github.com/leemcalilly/1f1e584f56aef15e7af1
Other relevant files:
* models/photo.rb - https://gist.github.com/leemcalilly/95c54a5df4e4ee6518da
* controllers/photos_controller.rb - https://gist.github.com/leemcalilly/c0723e6dc5478b0f914d
* uploaders/image_uploader.rb - https://gist.github.com/leemcalilly/5e43f6524734991773ae
* views/photos/index.html.erb - https://gist.github.com/leemcalilly/a8c4c808e5e8a802933b
* views/photos/_form.html.erb - https://gist.github.com/leemcalilly/cd0fd518c1b47d9bfb62
* initializers/carrierwaver.rb - https://gist.github.com/leemcalilly/49e04fa1dda891dd108b
The rails guides provides the solution. Use the fetch
method in the same way as the require
method. Note a second argument: it supplies the default value. So, if the params[:photo]
would not be found, the default value (an empty hash, as of the example below) will be returned:
params.fetch(:photo, {})
Sorry spotted this is bit late ,Ok now looking at your form code which look something like this
<%= form_for @photo, :html => {:multipart => true} do |f| %>
<% if @photo.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@photo.errors.count, "error") %> prohibited this photo from being saved:</h2>
<ul>
<% @photo.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<fieldset>
<legend>Upload a Photo</legend>
<div class="field">
<%= f.file_field :image %>
</div>
</fieldset>
<%= f.submit "Upload Photo", :class => "btn btn-small" %>
<% end %>
Now there this is not a problem with rails
or carrierwave
or strong_parameter
it is something how html
works . It like this, if you have file
input and if nothing
is attached to it the name
and value
pair is not sent to the server by HTML
think of it something like checkbox
or disabled
field
Now since your form only contain
<%= f.file_field :image %>
and it does not contain any other field (attributes of photo model)
therefore the photo
hash would not get constructed when the file
input does not
contain any attachment
which is evident in your log as well
Parameter (without attachment attached) =>
{"utf8"=>"✓", "authenticity_token"=>"IvOieBvxdA6qzVKrt1dYBuCXlt+uuWCyWjUAuTK0XEU=", "commit"=>"Upload Photo"}
Parameter (with attachment attached) =>
{"utf8"=>"✓", "authenticity_token"=>"I4O0w+Wk8nJaD6HJRSC+FfuAip5NVE6TkCUFDEN+sW0=", "photo"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007fc730b5de08 @tempfile=#<Tempfile:/var/folders/0m/n32lgww55vzf5pfc4kh17gm00000gr/T/RackMultipart20130801-32602-1nj6u2b>, @original_filename="bag.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"photo[image]\"; filename=\"bag.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Upload Photo"}
now you can see the difference between the two and that the difference is the reason of your error because in
1st case
params[:photo].present?
=> false
2nd case
params[:photo].present?
=> true
and hence when you do this params.require(:photo).permit(:image)
the code throws the errors
because of the line mention that .require(:photo)
which is not
present in params
Solution:-
Perhaps you can do something like this
def photo_params
if params[:photo].present?
params.require(:photo).permit(:image)
end
end
Conclusion :-
It not anyone fault because that is how the HTML
work if no
attachment no
name=value
pair submitted to server and because of which photo
params is not sent to server hence the hash is does not have them and hence strong parameter throws the error
Hope this help