I got an error while setting up a polymorphic file upload with the paperclip gem on Ruby on Rails.
In the following, I will show you the relevant code parts.
I've set up a _form partial:
<%= form_for(#test_run, :html => { :multipart => true }) do |f| %>
<div class="row">
<div class="large-6 columns">
<%= fields_for :attachment do |attachment_fields| %>
<%= attachment_fields.file_field :attachment %><br />
<% end %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit t('buttons.general.save'), :class => "button slim", data: {disable_with: "#{t('buttons.general.disable')}"}, :alt => t('buttons.general.save'),:title => t('buttons.general.save') %>
</div>
</div>
My attachment model contains the file validation:
class Attachment < ActiveRecord::Base
belongs_to :attachable, :polymorphic => :true
has_attached_file :attachment
validates_attachment_content_type :attachment, content_type: /\A(image|application)\/.*\z/
end
In the attachment controller I whitelist the following parameters:
def attachment_params
params.require(:attachment).permit(:name, :user_id, :attachable_id, :attachable_type, :attachedfile)
end
The attachment should be attached to a test run. Here is the test run model:
class TestRun < ActiveRecord::Base
belongs_to :test_object
has_many :attachments, :as => :attachable
accepts_nested_attributes_for :attachments
end
The create method and the private methods of the test runs controller could be relevant, too:
def create
#test_run = TestRun.new(test_run_params)
attachment = Attachment.create(:attachable_id => #test_run_id, :attachment => params[:attachment])
render text: #test_run.attachments.first.inspect
end
private
# Use callbacks to share common setup or constraints between actions.
def set_test_run
#test_run = TestRun.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def test_run_params
params.require(:test_run).permit(:name, :test_object_id, :attachment, :start_time, :end_time, :test_demands, :allowed_bug_types, :max_testers, :test_language, :postprocessing_time, :test_standards, :target_tester, :target_devices)
end
To give you a completely overview, here is the attachment migration file:
class CreateAttachments < ActiveRecord::Migration
def change
create_table :attachments do |t|
t.string :name
t.integer :user_id
t.integer :attachable_id
t.string :attachable_type
t.timestamps null: false
end
end
end
Now, when I run this, fill out the form and select a valid file and submit the form after this, I receive the following error:
Paperclip::AdapterRegistry::NoHandlerError in TestRunsController#create
Ok, somehow, stackoverflow shrinks the error message, so I put it on pastebin.
If hope, someone of you could help me, as I am on this point since days of researching for bugs.
Thank you!
run migration:
rails generate paperclip attachment attachment
in your view:
<%= fields_for :attachment do |field| %>
<%= field.file_field :attachment %><br />
<% end %>
your attachment_params
def attachment_params
params.require(:attachment).permit(:name, :user_id, :attachable_id, :attachable_type, :attachment)
end
your method create
def create
#test_run = TestRun.new(test_run_params)
attachment = Attachment.create(attachment_params)
render text: #test_run.attachments.first.inspect
end
you must also included in this controller method attachment_params
Related
I know there are alot of these kinds of posts on SO, and I think Ive read and tried each of them, all without success.
I have Post and Image models that I need to work together with a many to one relationship.
class Post < ActiveRecord::Base
has_many :images
end
class Image < ActiveRecord::Base
belongs_to :post
mount_uploader :file, images_uploader
end
Here is the post_parms declaration in my posts controller, which includes all of the fields in my image model migration.
private
def post_params
params.require(:post).permit(:title, :content, image_attributes: [:id, :post_id, :file])
end
and here is my post creation form where, I hope to allow multiple image asset creation with each post.
<%= form_for #post, html: {class: "pure-form pure-form-stacked"} do |post| %>
<%= post.fields_for :image, :html => { :multipart => true } do |image| %>
<%= image.label :file, "Upload Image:" %>
<%= image.file_field :file, multiple: true %>
<% end %>
<fieldset class="post-form">
<%= post.label :title %>
<%= post.text_field :title %>
<%= post.label :content %>
<%= post.text_area :content, :class => "redactor", :rows => 40, :cols => 120 %>
</fieldset>
<div class = "button-box">
<%= post.submit class: "pure-button pure-button-primary" %>
<%= link_to "Cancel", posts_path, :class => "pure-button" %>
</div>
Despite repeated effort and reading every post I can find on this topic, I'm still getting:
Unpermitted parameters: image
The trouble here is that this error provides no clue where to start looking for the problem. Since Im not really sure where to look next I thought I would post it here looking for more professional opinions.
Update the Post model as below:
class Post < ActiveRecord::Base
has_many :images
accepts_nested_attributes_for :images ## Add this
end
This way upon form submission you would receive the image attributes in key images_attributes and not image which you are currently receiving which is causing the warning as Unpermitted parameters: image
As you have 1-M relationship between Post and Image
You need to update post_params as below:
def post_params
params.require(:post).permit(:title, :content, images_attributes: [:id, :post_id, :file])
end
Use images_attributes (Notice plural images) and NOT image_attributes (Notice singular image)
And change fields_for in your view as
<%= post.fields_for :images, :html => { :multipart => true } do |image| %>
Use images (Notice plural) and NOT image (Notice singular)
UPDATE
To resolve uninitialized constant Post::Image error
Update Image model as below:
class Image < ActiveRecord::Base
belongs_to :post
## Updated mount_uploader
mount_uploader :file, ImagesUploader, :mount_on => :file
end
Also, suggested to remove multiple: :true from
<%= ff.file_field :file, multiple: true %>
I'm having an inordinate amount of trouble using a nested model with fields_for in a form. Specifically, not all of the nested fields save. A User has many Experiences, but when I submit the form, an Experience with the correct user_id but NO CONTENT is inserted into the database.
Looking at the logs, I also get an error:
unpermitted parameters: experience.
Rails 4 nested attributes not saving doesn't help, unfortunately.
Here's the code:
SCHEMA
create_table "experiences", force: true do |t|
t.string "content", null: false, default: ""
t.integer "user_id"
end
MODEL
#user.rb
class User < ActiveRecord::Base
has_many :experiences
accepts_nested_attributes_for :experiences
#experience.rb
class Experience < ActiveRecord::Base
belongs_to :user
end
CONTROLLER
class UsersController < ApplicationController
def new
#user = User.new
#user.experiences.build
end
def update
#user = current_user
#user.experiences.build
#user.update!(user_params)
redirect_to root_path
end
def user_params
params.require(:user).permit(:username, :email, :password,
:password_confirmation, :title, :blurb, :city, :state,
:style_list, :experience_attributes => [:id, :content])
end
VIEW
<%= form_for #user do |f| %>
<!-- (Omitted) user fields -->
<%= f.fields_for :experience do |experience_fields| %>
<%= experience_fields.text_field :content, placeholder: 'Content' %>
<% end %>
<%= f.submit 'Edit profile' %>
<% end %>
Any help would be greatly appreciated!
Here's your problem:
#user.experiences.build # -> note "experience**s**"
This means when you use fields_for, you have to reference :experiences (you're currently referencing the singular):
<%= f.fields_for :experiences do |experience_fields| %>
<%= experience_fields.text_field :content, placeholder: 'Content' %>
<% end %>
This also goes for your strong_params:
params.require(:user).permit(experiences_attributes: [:id, :content])
I have a has_many images association where i try to upload multiple images in a form but i am unable to see the associated attributes when i click the submit button.Its a simple association of bug has_many images and images belongs_to bug.I am using jQuery-File-Upload for file upload.The association is as shown :-
my first model
class Bug < ActiveRecord::Base
has_many :bug_images, :dependent => :destroy
accepts_nested_attributes_for :bug_images, :allow_destroy => true
attr_accessible :bug_images_attributes
has_attached_file :bug_image,
:styles => { :thumb => "75x75>", :small => "150x150>" },
:url => '/:class/:id/:attachment?style=:style'
end
my second model
class BugImage < ActiveRecord::Base
belongs_to :bug
def image_file=(input_data)
self.name = input_data.original_filename
self.image_type = input_data.content_type.chomp
self.size = File.new(input_data).size
end
end
my table definition
class CreateBugImages < ActiveRecord::Migration
def self.up
create_table :bug_images do |t|
t.string :name
t.references :bug
t.string :image_type
t.integer :image_size
t.timestamps
end
end
def self.down
drop_table :bug_images
end
end
##my view page where i can upload multiple file uplaod but on submit unable to get the uploaded images
<% form_for(#bug, :url => "/myapp/bugs/create",:html=>{:multipart => true,:id=>"form_bug"}) do |f| %>
<div class="row-fluid">
<label class="FormLabel">Severity <font color="red">*</font></label>
%= f.select :sevearity,Bug::Severity_Type ,{:prompt => "Select Severity Level"},:class=>'selectpicker'} %> </div>
<div class="row-fluid">
<label class="FormLabel">Attribute<font color="red">*</font></label>
<%= select_tag 'attribute_id', options_for_select(#attributes.collect{ |u| [u.attribute_name, u.id]}.insert(0, "")), :class=>'chzn-select',:required=>:true %>
</div>
<!-- here i upload multiple images for a bug ->
<% f.fields_for :bug_images do |builder| %>
<%= builder.file_field :image_file %>
<% end %>
<%end%>
my server log where i cant see the bug_images_attributes
"---------in create--------------"
"bug"=>{"sevearity"=>"S1"}, "attribute_id"=>"7", "controller"=>"bugs", "action"=>"create", "HTTP_START_TIME"=>20
13-10-08 18:56:01 +0530}
">>>>>>>>>>>>>>>> application_api"
if you want to attach multiple images to a bug, the bug_image model should have the has_attached_file declaration.
class Bug
has_many :bug_images
end
class BugImage
belongs_to :bug
has_attached_file :bug_image
end
I'm getting a mass assignment error when submitting a nested form for a has_one polymorphic model. The form is trying to create Employee and Picture instances based on the polymorphic association Rails guide.
I would appreciate literally ANY functioning example of a nested creation form for a has_one polymorphic model! I know there are tons of questions on mass assignment errors but I've never seen a working example with polymorphic associations.
Models
class Picture < ActiveRecord::Base
belongs_to :illustrated, :polymorphic => true
attr_accessible :filename, :illustrated
end
class Employee < ActiveRecord::Base
has_one :picture, :as => :illustrated
accepts_nested_attributes_for :picture
attr_accessible :name, :illustrated_attribute
end
Migrations
create_table :pictures do |t|
t.string :filename
t.references :illustrated, polymorphic: true
end
create_table :employees do |t|
t.string :name
end
controllers/employees_controller.rb
...
def new
#employee = Employee.new
#employee.picture = Picture.new
end
def create
#employee = Employee.new(params[:employee])
#employee.save
end
...
Error
Can't mass-assign protected attributes: illustrated
app/controllers/employees_controller.rb:44:in `create'
{"utf8"=>"✓", "authenticity_token"=>"blah"
"employee"=>{"illustrated"=>{"filename"=>"johndoe.jpg"},
"name"=>"John Doe"},
"commit"=>"Create Employee"}
In the models, I've tried every permutation of :illustrated, :picture, :illustrated_attribute, :illustrated_attributes, :picture_attribute, :picture_attributes, etc. Any tips or examples?
EDIT:
_form.html.erb
<%= form_for(#employee) do |f| %>
<%= f.fields_for :illustrated do |form| %>
<%= form.text_field :filename %>
<% end %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
You need to specify the nested_attributes appropriately. accepts_nested_attributes_for takes the name of the association as parameter and then you need to add the same assoc_attributes to your attr_accessible. So change your Employee model to
class Employee < ActiveRecord::Base
has_one :picture, :as => :illustrated
accepts_nested_attributes_for :picture
attr_accessible :name, :picture_attribute
end
And change the field_for line in the view code to
<%= f.fields_for :picture do |form| %>
I have a Carrierwave image upload in a nested simple_form which works (sort of) unless the user does not specify a file, in which case a blank Picture object is created unless there was a previously existing one. Not quite sure how to make it so that if the user doesn't specify a "new" image to upload, the old one isn't deleted and/or a blank record without a file is created.
One (maybe odd) thing I am doing is always sending the logged in #user to the user#edit action, then building a #user.picture if it doesn't exist. I am thinking this is where my bad design is.
# user.rb
class User < ActiveRecord::Base
[...]
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture
[...]
end
# picture.rb
class Picture < ActiveRecord::Base
attr_accessible :image, :remove_image
belongs_to :user
mount_uploader :image, ImageUploader
end
# users_controller.rb
def edit
if #user.picture.nil?
#user.build_picture
end
end
#_form.html.erb
<%= simple_form_for #user, :html => {:multipart => true} do |f| %>
<%= render "shared/error_messages", :target => #user %>
<h2>Picture</h2>
<%= f.simple_fields_for :picture do |pic| %>
<% if #user.picture.image? %>
<%= image_tag #user.picture.image_url(:thumb).to_s %>
<%= pic.input :remove_image, :label => "Remove", :as => :boolean %>
<% end %>
<%= pic.input :image, :as => :file, :label => "Picture" %>
<%= pic.input :image_cache, :as => :hidden %>
<% end %>
<br/>
#rest of form here
<% end %>
I think I had the same issue which I solved by adding a reject_if option to the accepts_nested_attribute. So in your example, you could do something like
class User < ActiveRecord::Base
[...]
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture,
:reject_if => lambda { |p| p.image.blank? }
[...]
end
When you use build_* it sets the foreign key on the object. ( similar to saying Picture.new(:user_id => id) )
Try This
# users_controller.rb
def edit
if #user.picture.nil?
#user.picture = Picture.new
end
end
Today I had the same problem, I solved this like:
accepts_nested_attributes_for :photos,
:reject_if => :all_blank