I have 2 models Post and Photo:
class Post < ActiveRecord::Base
has_many :photos
end
and :
class Photo < ActiveRecord::Base
belongs_to :post
has_attached_file :photo,styles:{medium:"300x300>", small:"100x100>"}
validates_attachment_content_type :photo, :content_type => /\Aimage\/.*\Z/
validates :photo, presence: true
end
I made a single change to photos_controller so photos could be uploaded, I added :photo:
def photo_params
params.require(:photo).permit(:post_id, :photo)
end
But when I want to add a new photo I get this warning in log:
Unpermitted parameters: post
And here is the parameters:
Processing by PhotosController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gSiLdGHe3VM8Ka6gjTKk7xjcK0omPdvqfQ0DRRXdOKo=",
"photo"=>{"post"=>"1"}, "commit"=>"Update Photo", "id"=>"1"}
Note: I have a photo attribute in my Photo model but I think thats not going to make any problems and I'm using paperclip gem for uploading images.
From what I see in the parameters sent to the server, post (not post_id) is set to 1.
Rails tells you that you're trying to assign post, an unpermitted parameter, to 1 (while you only permitted post_id in your photo_params method).
Related
I have 3 models :
User
Dish
Dish_Image
and I am using devise, paperclip and aws s3 to create users and attach images to the dishes.
Question : The dish is getting created and associated correctly to the user, but the image information is not getting inserted into the dish_image table and no errors are seen anywhere.
I have provide snippets of code what I think may be necessary, but please let me know if any more information is needed.
The app/models/user.rb
Class User < ActiveRecord::Base
has_many :dishes
The app/models/dish.rb
class Dish < ActiveRecord::Base
belongs_to :user, dependent: :delete
has_many :dish_images
accepts_nested_attributes_for :dish_images
The app/models/dish_image.rb
class DishImage < ActiveRecord::Base
belongs_to :dish, dependent: :delete
has_attached_file :d_image, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'
}
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :d_image, :content_type => /\Aimage\/.*\Z/
end
My dish_images_controller.rb file for create reads
def create
#dish = Dish.find(params[:dish_id])
#dish_image = #dish.dishimages.build(dish_image_params)
if #dish_image.save!
flash[:success] = "Image has been uploaded!"
else
flash[:notice] = "Image upload did not work!"
end
end
private
def dish_image_params
params.require(:dish_image).permit(:d_image)
end
The view for upload is
%h2 New Dish
= bootstrap_form_for([current_user, #dish], :html => { :multipart => true }) do |f|
%div
= f.text_field :title, autofocus: true
%div
= f.text_field :desc, autofocus: true
%div
= f.fields_for :dish_images do |ff|
Dish Image:
= ff.file_field :d_image, hide_label: true
%div= f.submit "Submit Dish"
and rake routes gives:
user_dish_dishimages GET /users/:user_id/dishes/:dish_id/dishimages(.:format) dishimages#index
POST /users/:user_id/dishes/:dish_id/dishimages(.:format) dishimages#create
user_dish_dishimage DELETE /users/:user_id/dishes/:dish_id/dishimages/:id(.:format) dishimages#destroy
Question : The dish is getting created and associated correctly to the user, but the image information is not getting inserted into the
dish_image table and no errors are seen anywhere.
Firstly, when the nested form is submitted, the create action of DishesController would be called. In order to save the dish_images records, you would need to whitelist dish_images_attributes in DishesController.
For example:
def dish_params
params.require(:dish).permit(:title, :desc, dish_images_attributes: [:id, :d_image])
end
NOTE: If you already have dish_params method to whitelist the attributes you would just need to update the arguments passed to permit in it. If your method for whitelisting attributes is named other than dish_params then update it accordingly.
I'm new to Rails and built something based on this
http://railscasts.com/episodes/403-dynamic-forms
but I have a problem with storing data in the additional fields...
I have a ProductType object that has many ProductField objects. The ProductField object also belongs to a ProductType and Product object belongs to a ProductType.
So,new dynamic fields can easily be added via the constructor ProductType, but when I try to set data in this fields via Product controller nothing happens.
I am sure that problem is related to use strong parameters, but fix described here and here did't help.
product.rb
class Product < ActiveRecord::Base
belongs_to :product_type
serialize :properties, Hash
end
product_type.rb
class ProductType < ActiveRecord::Base
has_many :fields, class_name: "ProductField"
accepts_nested_attributes_for :fields, allow_destroy: true
end
product_field.rb
class ProductField < ActiveRecord::Base
belongs_to :product_type
end
products_controller.rb
class ProductsController < ApplicationController
def new
#product = Product.new(product_type_id: params[:product_type_id])
end
def product_params
params.require(:product).permit(:name, :price, :product_type_id, {:properties => []})
end
product_type_controller.rb
class ProductTypesController < ApplicationController
def product_type_params
params.require(:product_type).permit(:name, fields_attributes: [:id, :name, :field_type, :required, :product_type_id])
end
In console log:
Unpermitted parameters: properties
Started PATCH "/products/4" for 127.0.0.1 at 2013-10-04 22:54:59 +0400
Processing by ProductsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"my3ra60OUXexmmguk2eqRetizx3tWPMq04Z2PnODJMQ=", "product"=>{"product_type_id"=>"1", "name"=>"Product1", "properties"=>{"gjfghjf"=>"123", "123"=>[""]}, "price"=>"10"}, "commit"=>"Update Product", "id"=>"4"}
Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", "4"]]
Unpermitted parameters: properties
P.S: maybe someone faced a similar problem when watching a podcast?
If you want to return a nested hash as a parameter you have to name the keys in the array in permit.
class ProductsController < ApplicationController
def new
#product = Product.new(product_type_id: params[:product_type_id])
end
def product_params
params.require(:product).permit(:name, :price, :product_type_id, {:properties => [:foo, :bar, :id]})
end
If you are generating the keys dynamically and can't code them into the permit statement then you need to use this style:
def product_params
params.require(:product).permit(:name, :price, :product_type_id).tap do |whitelisted|
whitelisted[:properties] = params[:product][:properties]
end
end
It's not the most friendly code for a new user, I just finished the 3 course rails certificate at UW and they never even covered .tap.
This is not my work, I'm still just understanding the deeper parts of .permit like this. This is the blog entry I used: Strong Parameters by Example
I seem to be unable to delete items using the accepts_nested_attributes_for command but I have done this according to this tutorial and the associated git repo. My models are ...
class Job < ActiveRecord::Base
has_many :specialties, :inverse_of => :job
accepts_nested_attributes_for :specialties, allow_destroy: true, :reject_if => :all_blank
end
class Specialty < ActiveRecord::Base
belongs_to :job, :inverse_of => :specialties
end
In my Job form, I have...
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Specialty" %>
When I click the checkbox to delete the a couple of specialties, nothing happens. I checked the server output and received:
Started PATCH "/jobs/1" for 127.0.0.1 at 2013-07-16 16:15:16 -0400
Processing by JobsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8VxYXujcKXpLEm8+7B43SLU6X3fH00kIOmFK+nvaBKs=", "job"=>{"name"=>"Cook", "description"=>"Makes the food.", "specialties_attributes"=>{"2"=>{"name"=>"", "description"=>"", "_destroy"=>"1", "id"=>"3"}, "3"=>{"name"=>"", "description"=>"", "_destroy"=>"1", "id"=>"4"}}}, "commit"=>"Update Job", "id"=>"1"}
Job Load (0.1ms) SELECT "jobs".* FROM "jobs" WHERE "jobs"."id" = ? LIMIT 1 [["id", "1"]]
Unpermitted parameters: _destroy
Unpermitted parameters: _destroy
Unpermitted parameters: _destroy
Unpermitted parameters: _destroy
What did I miss? I've gone through the tutorial and repo a bunch of times and I can't see where I've gone off.
That's because of strong_parameters. You now have to permit keys. In your action:
params.permit(:_destroy)
I like #Damien Roche's answer but its just for not confusion to any one. follow this
In job_controller.rb
private
def job_params
params.require(:job).permit(:id, :description, :specialty_fields_attributes => [:id, :job_id, :avatar, :_destroy])
end
My models:
class NewsItem < ActiveRecord::Base
has_many :file_uploads, :as => :uploadable
accepts_nested_attributes_for :file_uploads, :allow_destroy => true
end
class FileUpload < ActiveRecord::Base
belongs_to :uploadable, :polymorphic => true
has_attached_file :upload, :styles => {:thumb => '100x100>'}
end
Form Code (nested within NewsItem)
...
<%= f.fields_for :file_uploads do |upload| %>
<div class="file_upload">
<%= upload.file_field :upload %>
</div>
...
<% end %>
...
On submit I get the following error: "unknown attribute: upload". Here are the params:
{"utf8"=>"✓",
"authenticity_token"=>"MBfxJ4XTizCXv3Mpu971VHCm60bS3Y84Kdxfe+VJD2w=",
"news_item"=>{"title"=>"",
"body"=>"",
"published_date"=>"",
"file_uploads_attributes"=>{"0"=>{"upload"=>#<ActionDispatch::Http::UploadedFile:0x000001070112a8 #original_filename="rails-dd352fc2630e5f9aa5685ef1d7fe5997.png",
#content_type="image/png",
#headers="Content-Disposition: form-data; name=\"news_item[file_uploads_attributes][0][upload]\"; filename=\"rails-dd352fc2630e5f9aa5685ef1d7fe5997.png\"\r\nContent-Type: image/png\r\n",
#tempfile=#<File:/var/folders/hb/2bkct63171lck8d3sg0xfq0c0000gn/T/RackMultipart20111204-3216-71in7a>>,
"name"=>"",
"caption"=>""}}},
"commit"=>"Create News item"}
I'm using Rails 3.1.3 and paperclip "~> 2.4".
I'd avoid generic terms like "uploadable" because the resultant term "upload" has the potential for collision.
youavmatchulsky's suggestions are good too - if you have attr_accessible anywhere you'll need to make file_uploads_attributes accessible as well.
Also, the params don't look like the form is multipart, so I'd force it with :multipart => true in the call to form_for
EDIT: Even though it's supposed to happen automagically, you may have to explicitly accept_nested_attributes_for the join, and then on the join model accept_nested_attributes_for :uploadable -- I've found anaf to be pretty weird with things like polymorphic joins sometimes
Restarting the rails app fixed the problem. I'm guessing I installed the gem but did not restart, leading to the error above. Lesson learned: always restart after installing a gem.
I've created a Post and a TagObject model as follows
class Post
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :tag_objects
#embeds_many :comments
references_one :uploader, :class_name => 'User'
mount_uploader :image, ImageUploader
validates_presence_of :image
attr_accessible :tag_objects, :image
end
class TagObject
include Mongoid::Document
field :name
field :tags, :type => Array
embedded_in :post, :inverse_of => :tag_objects
attr_accessible :name, :tags
end
and currently have a page submit a PUT to the update method of the Post controller. The update fails and I get the following in the WEBrick console.
Started POST "/posts/4d4a174fa729cf71c70000a8" for 127.0.0.1 at Wed Feb 02 21:52:09 -0500 2011
Processing by PostsController#update as HTML
Parameters: {"post"=>{"tag_objects"=>{"1"=>{"tags"=>{"1"=>"testingfds"}}}}, "authenticity_token"=>"OZ+eXzD5NyqUI4CzPadlFUMDwRrg4LsaQBs5i+J65tU=", "id"=>"4d4a174fa729cf71c70000a8"}
honeycomb_development['posts'].find({:_id=>BSON::ObjectId('4d4a174fa729cf71c70000a8')}, {}).limit(-1)
Completed in 2ms
Mongoid::Errors::InvalidType (Field was defined as a(n) Array, but received a ActiveSupport::HashWithIndifferentAccess with the value {"1"=>"testingfds"}.):
app/controllers/posts_controller.rb:39:in `update'
I have absolutely no idea how to fix it and any help would be greatly appreciated.
Yah, seems the problem was that it was trying to do
tags = {0=>'testingdfg'}
instead of doing
tags[0] = 'testingdfg'
and set it's contents like I was expecting. I just added some logic into the update method to do so, and it works fine.
In the model, put
field :tags, :type => Hash
instead of
field :tags, :type => Array