This is my first Rails 6 project. Stuck on this. Any advice would be appreciated.
I have a form on index.html.erb
<%= form_with model: #volunteer_submission do |form| %>
<%= form.text_field :email %>
<%= form.text_field :first_name %>
<%= form.text_field :last_name %>
<%= form.submit %>
<% end %>
with a controller
def create
#volunteer_submission = VolunteerSubmission.new(volunteer_submission_params)
#volunteer_submission.save
redirect_to #volunteer_submissions
end
def volunteer_submission_params
params.require(:volunteer_submission).permit(:email, :first_name, :last_name)
end
I get this
Started POST "/volunteer_submissions" for ::1 at 2020-03-29 13:55:38 -0700
Processing by VolunteerSubmissionsController#create as JS
Parameters: {"authenticity_token"=>"OIlkqKqXJeA7XjYPqQHubZFGm64ivCe+9fimFwO8uBrtXJ3iPyiIZbgWtWS4FXFnS+KhZYCT5CgzN76YCTqC+Q==", "email"=>"a", "first_name"=>"a", "last_name"=>"a", "commit"=>"Save "}
Completed 400 Bad Request in 2ms (ActiveRecord: 0.0ms | Allocations: 666)
ActionController::ParameterMissing (param is missing or the value is empty: volunteer_submission):
app/controllers/volunteer_submissions_controller.rb:16:in `volunteer_submission_params'
app/controllers/volunteer_submissions_controller.rb:10:in `create'
If I leave out the volunteer_submission_params..it will attempt it...but I think rolls back because I have the DB set up for it not to accept null values. So...I'm not sure why the params aren't passing.
Started POST "/volunteer_submissions" for ::1 at 2020-03-29 13:40:33 -0700
Processing by VolunteerSubmissionsController#create as JS
Parameters: {"authenticity_token"=>"1cpAIcVZuM/qcJdt1KNg2rYMIX58yDVCO5mRMXmbiUjMHr81cAseqJZN/TDYDFaGXGLPJhs7iIwhvQgr5g/RRg==", "email"=>"a", "first_name"=>"a", "last_name"=>"a", "commit"=>"Save "}
(0.3ms) BEGIN
↳ app/controllers/volunteer_submissions_controller.rb:11:in `create'
VolunteerSubmission Create (7.1ms) INSERT INTO "volunteer_submissions" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-03-29 20:40:33.125665"], ["updated_at", "2020-03-29 20:40:33.125665"]]
↳ app/controllers/volunteer_submissions_controller.rb:11:in `create'
(0.4ms) ROLLBACK
↳ app/controllers/volunteer_submissions_controller.rb:11:in `create'
Completed 500 Internal Server Error in 14ms (ActiveRecord: 7.8ms | Allocations: 3296)
ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR: null value in column "email" violates not-null constraint
routes
Rails.application.routes.draw do
resources :volunteer_submissions
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
get 'volunteers', to: 'volunteer_submissions#index'
root to: 'pages#home'
end
I believe your issue is the fact that you are sending your params without a volunteer_submission key.
Based on this method
def volunteer_submission_params
params.require(:volunteer_submission).permit(:email, :first_name, :last_name)
end
Your controller is expecting { "authenticity_token"=>"OIlkqKqXJeA7XjYPqQHubZFGm64ivCe+9fimFwO8uBrtXJ3iPyiIZbgWtWS4FXFnS+KhZYCT5CgzN76YCTqC+Q==", "volunteer_submission" => { "email"=>"a", "first_name"=>"a", "last_name"=>"a" }}.
the form should look like this <%= form_with(model: item, local: true) do |form| %> also in model: item you should put the name of your model rb file located in app/models
in my case its app/models/item.rb
so my form is <%= form_with(model: item, local: true) do |form| %>
for me I had this issue because I was using an html input inside the rails form and was passing in the name of value without the model name.
<% form_with model: order_item do |f| %>
<input type="number" name="weight_in_oz"></input>
<% end %>
params look like this
{"authenticity_token"=>"...", "weight_in_oz"=>"16", "commit"=>"Add To Cart", "controller"=>"order_items", "action"=>"create"} permitted: false>
I fixed this by adding the model name before the input name and put the attribute in an array which nests the attribute inside of a model hash inside of params.
<% form_with model: order_item do |f| %>
<input type="number" name="order_item[weight_in_oz]"></input>
<% end %>
and this is the params after just what I was expecting
{"authenticity_token"=>"....", "order_items"=>{":weight_in_oz"=>"16"}, "commit"=>"Add To Cart", "controller"=>"order_items", "action"=>"create"} permitted: false>
Related
I am wondering if someone could tell me why I am getting this error "undefined method '[]' for nil:NilClass". This happens when I remove a picture with cocoon and try update. The method works fine for adding pictures to the edited gallery but I am getting this error when removing and updating. I tried using unless #pictures.blank? end I am assuming the problem is when cocoon removes the picture but I am not sure what to do from there. the server error is,
Started PATCH "/galleries/41" for ::1 at 2017-05-07 16:03:02 +1000
Processing by GalleriesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"cG1UXCvODhYzqqAr++EAn8GvMVk7+t/eASkzDDOoPmJfw3l6ax/F2xXMhvs7FcrJ3LOuTd0sks5+2fb86kQv0Q==", "gallery"=>{"name"=>"Hellooo", "cover"=>"123456", "pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"47"}, "1"=>{"_destroy"=>"1", "id"=>"48"}}}, "commit"=>"Update Gallery", "id"=>"41"}
Gallery Load (0.0ms) SELECT "galleries".* FROM "galleries" WHERE "galleries"."id" = ? LIMIT ? [["id", 41], ["LIMIT", 1]]
Unpermitted parameter: pictures_attributes
(0.0ms) begin transaction
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.0ms) commit transaction
Completed 500 Internal Server Error in 4ms (ActiveRecord: 0.0ms)
NoMethodError (undefined method `[]' for nil:NilClass):
...
Perhaps if someone could explain this to me would be great!
_form.html.erb
<%= form_for(#gallery, multipart: true) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :cover %>
<%= f.text_field :cover %>
</div>
<div id="pictures">
<%= f.fields_for :pictures do |pic| %>
<%= render 'picture_fields', f: pic %>
</div>
<% end %>
<div class="links">
<%= link_to_add_association 'add picture', f, :pictures %>
<%= f.submit %>
</div>
<% end %>
_picture_fields.html.erb
<div class="nested-fields">
<div class="field">
<%= f.label :picture %>
<%= f.file_field :picture, multiple: true, name: "pictures[picture][]" %>
<%= link_to_remove_association "remove picture", f %>
</div>
</div>
GalleriesController
def update
#gallery = Gallery.find(params[:id])
if #gallery.update(gallery_params)
params[:pictures][:picture].each do |pic|
#pictures = #gallery.pictures.create!(picture: pic)
end
flash[:success] = "Gallery Updated!"
redirect_to root_url
else
render 'edit'
end
end
Edit: Added gallery_params
def gallery_params
params.require(:gallery).permit(:id, :name, :user_id, :cover, picture_attributes: [:id, :gallery_id, :picture, :_destroy])
end
EDIT: Added create action and server log using cocoon
def create
#user = User.first
#gallery = #user.galleries.build(gallery_params)
if #gallery.save
flash[:success] = "Picture created!"
redirect_to root_url
else
render 'new'
end
end
server log
Started POST "/galleries" for ::1 at 2017-05-10 13:18:43 +1000
Processing by GalleriesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"XU3z2jMdbselPJZ2SdZdGPwiAebiPznt8GWRqmbv8LM/MIxO+sNo1z2NTaDQ3nJNm0qaBJ66ny5254MPpHZaQQ==", "gallery"=>{"name"=>"Hello", "cover"=>"123456", "pictures_attributes"=>{"1494386318553"=>{"picture"=>#<ActionDispatch::Http::UploadedFile:0xac59228 #tempfile=#<Tempfile:C:/Users/Lee/AppData/Local/Temp/RackMultipart20170510-7596-16xlrir.jpg>, #original_filename="Skateboard 1.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"gallery[pictures_attributes][1494386318553][picture]\"; filename=\"Skateboard 1.jpg\"\r\nContent-Type: image/jpeg\r\n">, "_destroy"=>"false"}, "1494386321001"=>{"picture"=>#<ActionDispatch::Http::UploadedFile:0xac59150 #tempfile=#<Tempfile:C:/Users/Lee/AppData/Local/Temp/RackMultipart20170510-7596-jxo0st.jpg>, #original_filename="Skateboard 2.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"gallery[pictures_attributes][1494386321001][picture]\"; filename=\"Skateboard 2.jpg\"\r\nContent-Type: image/jpeg\r\n">, "_destroy"=>"false"}}}, "commit"=>"Create Gallery"}
User Load (0.0ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
(0.0ms) begin transaction
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.0ms) rollback transaction
Rendering galleries/new.html.erb within layouts/application
Rendered galleries/_picture_fields.html.erb (1.0ms)
Rendered galleries/_picture_fields.html.erb (0.5ms)
Rendered galleries/_picture_fields.html.erb (0.5ms)
Rendered galleries/_form.html.erb (42.0ms)
Rendered galleries/new.html.erb within layouts/application (58.5ms)
Completed 200 OK in 157ms (Views: 139.3ms | ActiveRecord: 0.0ms)
Mmmm. Confused. There is no params[:pictures] so that is obviously nil (check the log you posted at the top). So that is causing the error. If you are looking for the pictures posted, you should refer to params[:pictures_attributes], but not even sure what you are trying to do there: create an empty picture (again?) for each posted pictures? The pictures are saved by doing the gallery.update(gallery_params).
Note: iterating over the posted params is imho definitely wrong, because if one is deleted, it will still be posted with the nested parameter _destroy set to true, so it can be deleted correctly from the database, or if a picture already existed, it will also be posted again (and not saved, since it already exists).
[EDIT] Add short solution:
use f.fields_for :pictures in your view: this will iterate over the existing pictures a gallery has, and will allow to delete/edit existing, and add new pictures to a gallery
fix your gallery_params and allow pictures_attributes (instead of the singular form)(otherwise nothing is saved)
in your controller just write #gallery.update_attributes(gallery_params) and do not iterate over params[:pictures] at all (remove that part) and it should just work (because the update_attributes will already have done this, at least if you want to iterate manually use pictures_attributes)
It looks like your gallery_params method is not permitting your pictures_attributes. You didn't post that code but I noticed in the error log Unpermitted parameter: pictures_attributes which means that your strong parameters(the gallery_params method) is filtering those parameters out.
Basically the whole point of the strong parameters is to make sure that you only pass through keys that you actually want to get passed through. So your controller is like "Nobody told me I am supposed to accecpt picture_attributes so I won't allow them through." Then your code is expecting there to be a picture object in the pictures array, but the pictures array doesn't have the picture object causing an error.
Can you post the code for gallery params? Can you also post the contents of params? Full disclosure: I don't really know rails 5 so there could be some other stuff going on.
I'm trying to update multiple records. The form generates fine and submits fine and the data is sent. The records are looked up to update, but no data is ever saved. I have my controller logic, form logic and console dump below. I'm trying to duplicate what Anthony Lewis put together but I have a feeling I am not passing the right data into or defining correctly the params.require().permit() method. Thanks in advance for your help!
class ConfigController < ApplicationController
def edit
#services = Service.all
end
def update
params["service"].keys.each do |id|
#service = Service.find(id.to_i)
#service.update_attributes!(service_params)
end
redirect_to config_url
end
private
def service_params
params.require(:service).permit(:id, :client_id, :client_secret)
end
end
Form code is:
<%= form_for :service, :url => update_config_path, :html => { :class => "form-horizontal", :method => "put", :remote => true } do %>
<% #services.each do |s| %>
<%= fields_for "service[]", s do |service_field| %>
<fieldset>
<legend><%= s.name %></legend>
<div class="form-group">
<%= service_field.label :client_id, "Consumer Key", :class => "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= service_field.text_field :client_id, :class => "form-control" %>
</div>
</div>
<div class="form-group">
<%= service_field.label :client_secret, "Consumer Secret", :class => "col-sm-2 control-label" %>
<div class="col-sm-10">
<%= service_field.text_field :client_secret, :class => "form-control" %>
</div>
</div>
</fieldset>
<% end %>
<% end %>
<%= submit_tag %>
<% end %>
Console reads:
Started PUT "/config" for 127.0.0.1 at 2013-11-22 15:44:08 -0800
Processing by ConfigController#update as JS
Parameters: {"utf8"=>"✓", "service"=>{"1"=>{"client_id"=>"testid", "client_secret"=>"testsecret"}, "2"=>{"client_id"=>"testkey", "client_secret"=>""}, "3"=>{"client_id"=>"", "client_secret"=>""}}, "commit"=>"Save changes"}
Service Load (0.3ms) SELECT "services".* FROM "services" WHERE "services"."id" = $1 LIMIT 1 [["id", 1]]
Unpermitted parameters: 1, 2, 3
(0.1ms) BEGIN
(0.1ms) COMMIT
Unpermitted parameters: 1, 2, 3
{}
Service Load (0.2ms) SELECT "services".* FROM "services" WHERE "services"."id" = $1 LIMIT 1 [["id", 2]]
Unpermitted parameters: 1, 2, 3
(0.1ms) BEGIN
(0.1ms) COMMIT
Unpermitted parameters: 1, 2, 3
{}
Service Load (0.2ms) SELECT "services".* FROM "services" WHERE "services"."id" = $1 LIMIT 1 [["id", 3]]
Unpermitted parameters: 1, 2, 3
(0.1ms) BEGIN
(0.1ms) COMMIT
Unpermitted parameters: 1, 2, 3
{}
Redirected to http://localhost:3000/config
Completed 302 Found in 6ms (ActiveRecord: 1.1ms)
I found a solution, but perhaps it isn't the best. Let me know if someone has a better idea and I'd be happy to try it!
In the solution I updated my controllers update action and the service_params.
I passed id to service_params and called fetch method on the require method to get the correct params. I noticed that in the console it read Unpermitted parameters: 1, 2, 3 when it was saving each record indicating the params were an array and I also noticed in #Vijay's solution he tried to narrow down the params as well. After some Googling and console logging I came up with the code below.
def update
params["service"].keys.each do |id|
#service = Service.find(id.to_i)
#service.update_attributes!(service_params(id))
end
redirect_to config_url
end
def service_params(id)
params.require(:service).fetch(id).permit( :client_id, :client_secret )
end
What do you think?
Try this...
params.require(:service).permit( id: [ :client_id, :client_secret ] )
Your strong parameters line should be
params.require(:service).permit( [:id, :client_id, :client_secret ] )
This permits arrays of values
http://guides.rubyonrails.org/action_controller_overview.html#more-examples
Try this one and it will work.
Let me know if you get any issue
def service_params
params.require(:service).map do |_, p|
p.permit(:id, :client_id, :client_secret)
end
end
http://blog.sensible.io/2013/08/17/strong-parameters-by-example.html
Please try:
def update
Service.update(service_params.keys, service_params.values
end
def service_params
params.permit(service: [:client_id, :client_secret]).require(:service)
end
This is my login form
<%= form_for Customer.new, url: {action: :login} do |f| %>
<%= f.text_field :username,placeholder: 'Username or Email' %>
<%= f.password_field :password,placeholder: 'Password' %>
<%= f.submit 'Login' %>
<% end %>
This is my controller
def login
username = params[:username]
password = params[:password]
unless username.blank? && password.blank?
#My code doesn't entering to this block
end
end
If i submit form it is just submitted it doesn't perform any action
Edit 1
This is what my console return when form submitted
Started POST "/auth/login" for 127.0.0.1 at 2013-09-08 08:23:05 +0530
Processing by AuthController#login as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9f7TKlIspKQwX7jMSzI7XGrabgJKvnzj8Ip0OLTDtW4=", "customer"=>{"username"=>"xxx", "password"=>"[FILTERED]"}, "commit"=>"Login"}
Rendered auth/login.html.erb within layouts/application (3.5ms)
Rendered layouts/_header.html.erb (0.4ms)
Completed 200 OK in 21ms (Views: 19.3ms | ActiveRecord: 0.0ms)
If you check your params hash you'll see that those keys don't exist. Instead, you'll see that params[:custpmer] does and that it contains those fields. This is just how rails builds the params in a form_for style. So try this instead:
username = params[:customer][:username]
password = params[:customer][:password]
I am having difficulty translating the Headfirst into Rails book which is based on Rails 2 into Rails 4 which is set up on my machine.
The exercise is trying to retrieve a record from a database and then, once edited, update the table.
I have tried many different ways and my current configuration is as follows - this will present the record for editing but will not actually update the record! (Infuriating!)
NB - I am not using 'strong_parameters' nor 'protected_attributes' - I did try this but was getting stack to deep and other errors.
My ad model is also empty - I have removed the att_accessible entries that I tried with the protected attributes gem.
Here is my - ad controller entry:
def update
#ad = Ad.find(params[:id])
#ad.update_attributes(update_params[:id])
redirect_to "/ads/#{#ad.id}"
end
private
def update_params
params.permit(:name, :description, :price, :seller_id, :email, :ad, :img_url)
end
end
EDIT VIEW:
<h1>Editing <%= #ad.name %></h1>
<%= form_for(#ad,:url=>{:action=>'update'}) do |f| %>
<p><b>Name</b><br /><%= f.text_field :name %></p>
<p><b>Description</b><br /><%= f.text_area :description %></p>
<p><b>Price</b><br /><%= f.text_field :price %></p>
<p><b>Seller</b><br /><%= f.text_field :seller_id %></p>
<p><b>Email</b><br /><%= f.text_field :email %></p>
<p><b>Img Url</b><br /><%= f.text_field :img_url %></p>
<p><%= f.submit "update" %></p>
<% end %>
Log Entry on Update:
Started PATCH "/ads/1/update" for 127.0.0.1 at 2013-08-13 22:35:51 +0100
Processing by AdsController#update as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"O4cN72FXCCkfkL7M6bozodbB0Aqor
NctOOV5sfXdado=", "ad"=>{"name"=>"Typewriter", "description"=>"Old manual typewr
iter. Many years useful service. Works best with a bottle next to it.", "price"=
>"71.95", "seller_id"=>"54", "email"=>"dhammett#email.com1", "img_url"=>"http://
homepage.mac.com/david_griffiths/typewriter.png"}, "commit"=>"update", "id"=>"1"
}
←[1m←[35mAd Load (1.0ms)←[0m SELECT "ads".* FROM "ads" WHERE "ads"."id" = ? L
IMIT 1 [["id", "1"]]
Unpermitted parameters: utf8, _method, authenticity_token, ad, commit, id
←[1m←[36m (0.0ms)←[0m ←[1mbegin transaction←[0m
←[1m←[35m (0.0ms)←[0m commit transaction
Redirected to http://localhost:3000/ads/1
Completed 302 Found in 54ms (ActiveRecord: 1.0ms)
I'm creating a profile that is associated with a member id based on Devise authentication.
When creating the profile, the values aren't inserted into the database.
Routes file.
resources :troopers do
resource :trooper_profile
end
Trooper model
has_one :trooper_profile
Trooper Profile model
belongs_to :trooper
Trooper Controller #create action
def create
#trooper = current_trooper
#profile = #trooper.build_trooper_profile(params[:profile])
respond_to do |format|
if #profile.save
format.html { redirect_to(trooper_trooper_profile_path, :notice => 'Profile was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
Profile Form
<%= form_for #profile, :url => trooper_trooper_profile_path(#trooper) do |f| %>
<%= f.label :first_name %><br />
<%= f.text_field :first_name %><br /><br />
<%= f.label :last_name %><br />
<%= f.text_field :last_name %><br /><br />
<p><%= submit_tag "Create Profile" %></p>
<% end %>
Server output
Started POST "/troopers/1/trooper_profile" for 127.0.0.1 at 2011-05-20 13:04:01 +1000
Processing by TrooperProfilesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"LhT6b4xu5bIJ5kwhS74L7dpaGbuR5BTdirh9AziD+Ew=", "trooper_profile"=>{"first_name"=>"Robert", "last_name"=>"", "commit"=>"Create Profile", "trooper_id"=>"1"}
Trooper Load (0.5ms) SELECT "troopers".* FROM "troopers" WHERE ("troopers"."id" = 1) LIMIT 1
TrooperProfile Load (0.3ms) SELECT "trooper_profiles".* FROM "trooper_profiles" WHERE ("trooper_profiles".trooper_id = 1) LIMIT 1
Rendered trooper_profiles/_form.html.erb (11.7ms)
Rendered shared/_head.html.erb (1.6ms)
Rendered shared/_menutop.html.erb (1.2ms)
Rendered trooper_profiles/new.html.erb within layouts/application (18.5ms)
Completed 200 OK in 109ms (Views: 22.5ms | ActiveRecord: 0.8ms)
I've got this same setup in another application and can't see why this isn't working.
Change the following...
#profile = #trooper.build_trooper_profile(params[:trooper_profile])
It appears the parameters being passed are :trooper_profile
trooper_profile"=>{"first_name"=>"Robert", "last_name"=>"", "commit"=>"Create Profile", "trooper_id"=>"1"}
However, you're referencing :profile
If it's rendering the new view, then the profile isn't saving - perhaps it's a validation error? Does TrooperProfile require a last name (blank in your example)?