Rails 4 nested fields_for not saving - ruby-on-rails-4

I see many posts, but I am not sure they apply to my problem. Mainly because when I try to implement those solutions I get syntax errors. I don't know why this seems to be such a problem.
I have profile object that has a 1:1 relationship with user. In the edit of profile I want to save the email of user. But it will not save here is the code and output...
View:
= semantic_form_for #profile do |f|
= f.inputs class: "form-group" do
= f.input :name, input_html: { class: "form-control" }
= f.input :username, input_html: { class: "form-control" }
= f.semantic_fields_for #profile.user do |u|
= u.input :email, input_html: { class: "form-control" }
The paramaters being passed to the controller:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"iMkkLX6qN7PagmbnEQlQZ0CH5Q/fl+G9273eHFO9aRk8EG4MisEi3PwQOWocU2wp3UW5ju4DOJcUh5v19pS46A==", "profile"=>{"name"=>"John Doe", "username"=>"JohnnyD", "user"=>{"email"=>"jdoe#email.com"}, "commit"=>"Save", "controller"=>"profiles", "action"=>"update", "id"=>"4"}
The response from the controller:
Unpermitted parameter: user
The whitelisting:
params.require(:profile).permit(:name, :username, :user)
The models:
class Profile < ActiveRecord::Base
belongs_to :user
accepts_nested_attributes_for :user
end
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
I have tried adding users_attributes: [:email] to the required params #syntax error.
I have tried adding user: [:email] to the required prarams #syntax error
I have tried with and without accepts_nested_attributes in the model #no effect.
Can someone clue me in, because I am clearly clueless.
Thanks.

I see two problems:
First - = f.semantic_fields_for #profile.user do |u| Should be:
= f.semantic_fields_for users do |u|
(Here you are telling Rails to pick related Database table, so should be plural users)
And second - strong params should really be as you already tried:
params.require(:profile).permit(:name, :username, users_attributes: [:email])
Hope it fixes your issue.

Related

Unpermitted parameter with nested attributes

I am trying to use the accepts_nested_attributes_for, but I get an unpermitted parameters: address when I try to create or update a field in the address model
I have a relationship between two models a Client which has an Address as follows
class Client < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
...
class Address < ActiveRecord::Base
belongs_to :client
The strong parameters are set up according to this http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
as follows
def client_params
params.require(:client).permit(:name, :tel, :email, :website, :photo,
address_attributes: [:id, :line1, :line2,
:town, :country, :zip_code])
end
The update action in the controller uses client_params
def update
#client = Client.find(params[:id])
if #client.update(client_params)
...
the form uses form_for and field_for
form_for :client, url: path, method: mymethod, html: {multipart: true, role:'form'} do |f|
= f.text_field :name
...
= f.fields_for :address do |a|
= a.text_field :line1, label: 'First line'
= a.text_field :line2, label: 'Second line'
= a.text_field :town
= a.text_field :country
= a.text_field :zip_code
The client fields work fine. However, if i try to update one of the address fields the address in not updated and unpermitted parameter: address is logged.
Here are the parameters from such a request
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"Yx+ualZcCUZTriCIiCfF1SrFVUGdOnFgWApiYqKAMXU=",
"client"=> {
"name"=>"Alice",
"email"=>"",
"tel"=>"",
"website"=>"",
"address"=> {
"line1"=>"Casa 1",
"line2"=>"",
"town"=>"",
"country"=>"",
"zip_code"=>""}},
"commit"=>"Save Details",
"id"=>"16"}
My earlier answer was mostly irrelevant. Here's what I think the problem is, the nested attributes in the params require must reference plural of the model name.
Where you have address_attributes: must be plural addresses_attributes:
I think that's the problem.
def client_params
params.require(:client).permit(:name, :tel, :email, :website, :photo,
addresses_attributes: [:id, :line1, :line2,
:town, :country, :zip_code])
end
Please let me know how it goes.

Rails4 Simple_form nested form field not displaying

I am a newbie to Ruby on Rails and have scoured Stackoverflow and the internet to the best of my abilities and am still stumped.
In my set-up, a Rating belongs_to a Product and has_many Comments. I'm using simple-form and trying to use nested fields_for to add RatingComment through the Rating form. Interestingly, when using the singular form of :rating_comment, the field is displayed. But as expected, I get the unpermitted parameter error when trying to save. When I use plural :rating_comments, the field disappears. This is similar to this SO posting, but adding #rating.rating_comments.build to new action still does not work for me. I've tried restarting the server many times, and even reset the database to no avail. Would appreciate any assistance as I've been struggling with this issue for the past few days.
Note: I've also taken out what I think is irrelevant code from the snippets below. If I need to show more information, please do let me know. Thanks in advance!
routes.rb
resources :ratings, only: [:new, :create, :edit, :update, :destroy] do
resources :rating_comments, shallow: true
end
rating.rb
class Rating < ActiveRecord::Base
belongs_to :product
belongs_to :user
has_many :rating_comments, foreign_key: "rating_id", dependent: :destroy
accepts_nested_attributes_for :rating_comments, reject_if: :all_blank
end
rating_comment.rb
class RatingComment < ActiveRecord::Base
belongs_to :rating
validates :rating_id, presence: true
end
ratings_controller.rb
class RatingsController < ApplicationController
before_action :signed_in_user, only: [:create, :new, :show]
def new
#product = Product.find(params[:id])
#rating = #product.ratings.new
#rating.rating_comments.build
end
def create
#product = Product.find(params[:product_id])
#rating = #product.ratings.build(rating_params)
#rating.user_id = current_user.id
...
private
def rating_params
params.require(:rating).permit(:user_id, :product_id, :rating, rating_comments_attributes: [:rating_id, :content])
end
end
ratings/_new_rating_form.html.erb
<%= simple_form_for([#product, #rating], html: { class: 'form-horizontal' }) do |f| %>
<%= f.error_notification %>
<%= f.input :rating, collection: 1..10, as: :radio_buttons,
item_wrapper_class: 'inline', checked: 5 %>
<%= f.simple_fields_for :rating_comments do |rc| %>
<fieldset>
<%= rc.input :content, label: "Comments" %>
</fieldset>
<% end %>
<%= f.error :base %>
<%= f.button :submit, "Submit" %>
<% end %>
Very embarrassed to admit that it turns out that I had the view written in the wrong action. Once I put it in the new.html, it finally worked.

ActiveAdmin deleting attached CarrierWave images on form submission

I'm not sure what I'm doing wrong here. File uploads are working but if I submit the form without selecting a file to upload it deletes the previously attached image(s).
Here's what the ActiveAdmin form looks like:
form do |f|
f.inputs do
f.input :model_number
f.input :description
f.input :slug
f.input :categories
f.has_many :product_images do |image|
image.input :product_id, as: :hidden, id: :product_id, input_html: { value: "%i" }
image.input :image
end
end
f.actions
end
And the relevant parts of the respective models:
class ProductImage < ActiveRecord::Base
belongs_to :product
mount_uploader :image, ProductImageUploader
validates :image, :product_id, presence: true
end
class Product < ActiveRecord::Base
has_many :product_images, dependent: :destroy
accepts_nested_attributes_for :product_images
validates_associated :product_images
end
Any insights would be much appreciated. Thanks!
It looks like I was a bit overzealous with my validations. Removing product id from the ProductImages validations and simplifying image.input :product_id, as: :hidden, id: :product_id, input_html: { value: "%i" } in the form to image.input :product_id, as: :hidden in the form makes image attach correctly to existing products or new products.

Can't Save Image Attributes with Paperclip in Rails 4

I have two associated models in my Rails 4 app: product.rb and image.rb. The Image model allows attached files using the Paperclip gem.
Images belong_to a Product, and a product has_many Images.
I would like to use the Product's new view to create and attach an image when I create a product. Each time I try, the parameters associated with the Paperclip image do not get saved, and end up nil.
Here are the models:
Product.rb
class Product < ActiveRecord::Base
validates :name, :part_number, presence: true
has_many :images, dependent: :destroy
belongs_to :category
accepts_nested_attributes_for :images, allow_destroy: true
end
Image.rb
class Image < ActiveRecord::Base
belongs_to :product
has_attached_file :image
end
Looking through past Stack Overflow questions I've found some relevant questions and answers, but none that seem to help my particular situation. So far I'm able to submit the file with the correct attributes, but it doesn't save them to the database.
ProductsController#create
def create
#product = Product.new(product_params)
end
def product_params
params.require(:product).permit(:name,
:category_id,
:part_number,
images_attributes: [:image])
end
ProductsController#new
def new
#product = Product.new
#categories = # irrelevant to question
end
products/new.html.haml
= form_for #product, :html =>
= f.label :name
= f.text_field :name
= f.label :part_number
= f.text_field :part_number
= f.label :category_id
= f.select :category_id, #ca
= f.fields_for :image do |ff|
= ff.label :image
= ff.file_field :image
= f.submit('Create Product')
Looking at the parameters I can tell that the correct attributes are being passed on:
Example parameters:
{"utf8"=>"✓",
"authenticity_token"=>"jGNy/TasHzP0EcWDFzZ3XH5/fpxb6vD+ncQ2PZSQ3/I=",
"product"=>{"name"=>"bar",
"part_number"=>"foo",
"category_id"=>"30",
"image"=>{
"image"=>#<ActionDispatch::Http::UploadedFile:0x007fc82f58e0e0
#tempfile=#<Tempfile:/var/folders/04/23d9grkj5fv3wkj2t8858kx40000gn/T/RackMultipart20131029-64949-1ldkz4g>,
#original_filename="FPE230_b.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"product[image][image]\"; filename=\"FPE230_b.jpg\"\r\nContent-Type: image/jpeg\r\n">}},
"commit"=>"Create Product"}
However, the image is not actually being saved to the database. How can I rectify this?
EDIT
Looking more closely at the logs, I see that I'm getting an "unpermitted parameters: image" error. This is even after adding images_attributes: [:image] to my product_params method.
I was able to get a setup similar to yours working with the following changes:
In ProductsController#create, instead of building the image separately, let the nested attributes handle it and just do:
#product = Product.new(product_params)
And allow the nested parameters (I figured out the image_attributes: [:image] from this question):
def product_params
params.require(:product).permit(:name, :part_number, images_attributes: [:image])
end
This is what my parameters look like in the logs for a create request:
{
"utf8"=>"✓",
"authenticity_token"=>"7EsPTNXu127itgp4fbohu672/L4XnSwLEkrqUGec3pY=",
"product"=>{
"name"=>"whatever",
"part_number"=>"12345",
"images_attributes"=>{
"0"=>{
"image"=>#<ActionDispatch::Http::UploadedFile:0x007feb0c183b08
#tempfile=#<Tempfile:/var/folders/6k/16k80dds0ddd6mhvs5zryh3r0000gn/T/RackMultipart20131031-51205-emaijs>,
#original_filename="some-image.png",
#content_type="image/png",
#headers="Content-Disposition: form-data; name=\"product[images_attributes][0][image]\"; filename=\"ponysay.png\"\r\nContent-Type: image/png\r\n">
}
}
},
"commit"=>"Create"}
And I see an insert into products and an insert into images.
If that doesn't work, could you post your ProductsController#new and your new product form?
EDIT AFTER YOUR EDIT:
I have 3 different things in my app/views/products/new.html.erb and ProductsController#new that might be affecting your results:
In the form_for, I have multipart: true as in the paperclip documentation:
<%= form_for #product, :url => products_path, :html => { :multipart => true } do |f| %>
Because Product has_many :images, in my form I have fields_for :images instead of fields_for :image:
<%= f.fields_for :images do |i| %>
<%= i.file_field :image %>
<% end %>
This fields_for doesn't show anything on the page unless in the ProductsController#new I build an image; does your Product.new do this by any chance?
def new
#product = Product.new
#product.images.build
end
Are there any particular reasons for these differences you have? Does your code work if you change it to match mine?

Nested attributes - Unpermitted parameters Rails 4

There is a lot of resources on SO about issues on Nested attributes in Rails 4 regarding strong parameters but I don't find any solution on this: (so sorry if it's a duplicate)
I have a 1-1 relation between member and profile.
When trying to update a member with profile attributes I've got this error:
Unpermitted parameters: profile
Where are my params
===> params: {"member"=>{"profile"=>{"first_name"=>"test", "last_name"=>"test"}, "email"=>"test#test.com"}}
My models:
Member.rb
class Member < ActiveRecord::Base
...
has_one :profile
accepts_nested_attributes_for :profile
end
Profile.rb
class Profile < ActiveRecord::Base
belongs_to :member
end
My form:
edit.html.slim
= simple_form_for [:admin, #member] do |f|
= f.simple_fields_for #member.profile do |pf|
= pf.input :first_name
= pf.input :last_name
= f.input :email
= f.button :submit
and my controller:
admin/members_controller.rb
class Admin::MembersController < Admin::BaseController
before_action :set_member, only: [:edit]
def edit
end
def update
if #member.update(member_params)
Rails.logger.debug "===> (1)"
redirect_to edit_admin_member_path
else
render action: 'edit'
end
end
private
def set_member
#member = Member.find(params[:id])
end
def member_params
params[:member].permit(:email, profile_attributes: [:first_name, :last_name ])
end
end
I've tried many things but don't understand where is my mistake.. Moreover in the update method it says the #member is correctly updated (shown ===> (1))
Ok get it..
I think this is caused by simple_form:
= simple_form_for [:admin, #member] do |f|
= f.simple_fields_for :profile, #member.profile do |pf|
= pf.input :first_name
= pf.input :last_name
= f.input :email
= f.button :submit
Try Adding the :member_id inside profile_attributes which is in member_params
so it will look like this:
def member_params
params[:member].permit(:email, profile_attributes: [:first_name, :last_name, :member_id ])
end