This is a possible duplicate, but I have read and tried nearly all suggestions, but I keep getting the error on the New action view. I am using Rails 5.
I have tried the following:
private
def ph_params
params.require(:ph).permit(:amount)
end
And also tried the following, and the error disappeared, but my values were not saving to database, only shows Nil:
private
def ph_params
params.permit(:amount)
end
My controller:
class PhsController < ApplicationController
def index
end
def new
#ph = Ph.new(ph_params)
end
def create
#ph = Ph.new(ph_params)
respond_to do |format|
if #ph.save
format.html { redirect_to #ph }
else
format.html { render "new" }
end
end
end
def show
#ph = Ph.find(params[:id])
end
private
def ph_params
params.require(:ph).permit(:amount)
end
end
new.html.erb form start
<%= simple_form_for #ph, url: phs_path do |f| %>
Model
class Ph < ApplicationRecord
end
I might be missing something. Your assistance is appreciated, thank you in advance.
Modify your new action to
def new
#ph = Ph.new
end
The reason you're getting the error is because when you hit the route phs/new, no key ph is passed in the params hash to the controller but you're trying to access params[:ph][:amount] which is the return value of ph_params. This is why the error 'param is missing or the value is empty' occurs.
If you want to know what values were passed in the params has for every request, add the following line to your application.html.erb
<%= params.inspect %>
You'll probably find a hash with two keys {"controller" => "phs", "action" => "new"} in the new page.
However, when you try to create a new ph object, you will find a key ph in your params hash.
By the way, I think you don't quite understand strong parameters. I would suggest you to read http://api.rubyonrails.org/classes/ActionController/StrongParameters.html
Related
I am getting a 404 error on my RoR app and i found that it was because one of the method in the controller, which should only triggers when the record is not new, triggered when the record is new.
I do by that checking if the id of that record nil in my controller.
before_action :create_record, if: proc { not params[:id].nil? }
I was confused by it was triggered so i went head and checked my front-end network, which show following:
Request
Parameters:
{"format"=>"json", "id"=>"new"} <----Set to new by default
My completely controller looks like this:
class Api::MyController < ApplicationController
before_action :create_recotrd, if: proc { not params[:id].nil? }
def show
end
def index
#my_model = MyModel.all
end
def create
#my_model = MyModel.new(my_model_params)
respond_to do |format|
if #my_model.save
format.json { render json: #my_model, status: :created}
else
format.json { render json: #my_model.errors, status: :unprocessable_entity}
end
end
end
def update
#my_model = MyModel.update
end
private
def create_record
#my_model = MyModel.find(params[:id])
end
def my_model_params
params.require(:my_model).permit(
:city,
:state,
:county,
:zip,
:telephone,
:email,
)
end
end
I cant seem to find out why the id in the parameters is set to "new" instead of "nil".
I tried in the console by doing MyModel.new, the default id was nil, but then when i do the GET request, the id was set to "new"
This is a really weird approach to set a new record. I think the problem lies in your routes. You are probably trying to access yoursite.com/your_model/new and your routes are configured to look for
get "your_model/:id" => "your_controller#show"
You are probably missing
get "your_model/new" => "your_controller#new"
So when you try to visit your_model/new the routes map the "new" as the :id param in your url.
I don't see a new action in your controller as well. You should read up on basic resource set up for rails here: http://guides.rubyonrails.org/routing.html.
I'm having what I assume must be a simple problem but I just can't figure it out. I'm trying to update an attribute in one model when another is created.
In my view:
<%= link_to 'Click here to rate this user', new_user_review_path(:user_id => request.user.id, :gigid => request.gig.id), remote: true %>
Which passes params :gigid and :user_id
Than my controller:
def new
#review = Review.new
#gig = Gig.find(params[:gigid])
end
def create
#review = #user.reviews.new review_params
#review.reviewed_id = current_user.id
if #review.save
#gig.update(reviewed: true)
respond_to do |format|
format.html {redirect_to session.delete(:return_to), flash[:notice] = "Thankyou for your rating!"}
format.js
end
else
render 'new'
end
end
But I get undefined method 'update'for nil:NilCLass:
I know the params are passing and the 'Gig' can be updated as :
def new
#review = Review.new
Gig.find(params[:gigid]).update(reviewed: true)
end
updates the attribute fine, but when I click 'New review' not when the review is actually created.
Adding :
def create
#review = #user.reviews.new review_params
#review.reviewed_id = current_user.id
if #review.save
Gig.find(params[:gigid]).update(reviewed: true)
etc etc etc
gives me the same undefined method 'update'for nil:NilCLass:
I have tried with find_by_id instead of find which makes no difference.
EDIT:
def create
#gig = Gig.find params[:gigid]
#review = #user.reviews.new review_params
#review.reviewed_id = current_user.id
if #review.save
#gig.update(reviewed: true)
etc etc etc
Doesn't work either. I get no errors, but the gig ID is still 'nil'.
The params are passing to the 'New' action but not the 'Create' action. I feel this should be very easy but I'm just not seeing it at the moment.
But I get undefined method 'update'for nil:NilCLass:
The error is that you have not defined #gig in your create action.
Since Rails is built on HTTP, and HTTP is stateless, you have to set the "instance" variables with each new request:
def new
#review = Review.new
#gig = Gig.find params[:gigid]
end
def create
#gig = Gig.find params[:gigid]
#review = #user.reviews.new review_params
A much better pattern for you would be to use the after_create callback in your Review model:
#app/models/review.rb
class Review < ActiveRecord::Base
belongs_to :gig #-> I presume
after_create :set_gig
private
def set_gig
self.gig.update(reviewed: true)
end
end
--
If you wanted to make the Gig update within your current setup, you'll be best sending the gig_id param through the request (not the link):
#app/views/reviews/new.html.erb
<%= form_for [#user, #review] do |f| %>
<%= f.hidden_field :gig_id, #gig.id %> #-> params[:reviews][:gig_id]
...
<% end %>
This will make params[:review][:gig_id] available in the create action, with which you'll be able to use in your code.
The problem is, you never assigned a value to #gig in your create method. I can't see your form, but you need something like this in your create method:
#gig = Gig.find params[:gigid]
Assuming that you're passing the parameter :gigid to #create
In the second example you showed, I'm not sure what's going on, but you should be getting a ActiveRecord::RecordNotFound exception on the find().
Try the below code for update operation.
gig_record = Gig.find_by_id(params[:gigid])
gig_record.update_attribute(reviewed: true) unless gig_record.blank?
I am trying to submit a test post through my form, and I am getting this error: param is missing or the value is empty: content. I am requiring "content" and permitting a "title". Both fields were filled out when submitting the post or "thought" in my app. I believe the problem has something to do with strong parameters. I can't find the answer anywhere else on the internet. Here is my controller.
class ThoughtsController < ApplicationController
def index
end
def new
#thought = Thought.new(params[:id])
end
def create
#thought = Thought.new(params[post_params])
#thought.save
if #thought.save
redirect_to #thought
else
render :new
end
end
private
def post_params
params.require(:content).permit(:title)
end
end
Thanks for the help.
The following should work. You propably understand the strong_parameters a bit wrong. If your thought object has :content and :title attributes, they should be listed in permit parenthesis - this will mean you allow their mass-assignment.
def create
#thought = Thought.new(post_params)
if #thought.save
redirect_to #post
else
render :new
end
end
private
def post_params
params.require(:thought).permit(:content, :title)
end
When I initially call the new function all variables load up correctly. The params[:code] is a URL param defined in routes. However, when validation fails on create and new is rendered, the #m variable is not loaded (this causes a nomethoderror when an attribute of #m is called in the 'new' template). So, the :code parameter is not obtained after rendering new. However can the :code parameter be preserved after validation fails?
class AffiliatesController < ApplicationController
def new
#m = Merchant.find_by_code(params[:code])
#affiliate = Affiliate.new
end
def create
a = Affiliate.new(params[:affiliate])
if a.save
redirect_to 'http://' + params[:ref]
else
render 'new'
end
end
end
Another way to preserve params[:code], aside from using the session, is to add a hidden field in the form.
<%= form_for #affiliate do |f| %>
<%= hidden_field_tag :code, #m.code %>
Then change the create action to
def create
#affiliate = Affiliate.new(params[:affiliate])
if #affiliate.save
redirect_to 'http://' + params[:ref]
else
#m = Merchant.find_by_code(params[:code])
render :new
end
end
before you call render you should fill in all the variables that will be used by the view.
So in your case you need to instantiate #m = ... before you render 'new' from within the create as well.
If you need an extra parameter to accomplish this (the param[:code] in your case) I would not recomment you to configure routes and pass this information over the URI, it's complicated.
Use the session instead, it's a lot easier!
For example:
in index (or wherever you have the merchant code available) add session[:merchant_code] = the_code.
in new change #m = Merchant.find_by_code(session[:merchant_code])
Cheers,
I am having a model Factsheet which has some decimal columns, for entering some $ values(price). I need to be able to enter values like $1,000,000.00 and calculate the original value from them before saving. If I do the save, before any formatting, it will save it as 1.00 as "$1,000,000.00".to_f = 1.0 I was trying to do a before_save callback, and extract the digits and dots only from the column before saving it. Here is how I went about it:
class Factsheet < ActiveRecord::Base
before_save :convert_to_decimal
def convert_to_decimal
self.shopping_center_size = decimal_value(shopping_center_size)
self.cam = decimal_value(cam)
self.tax = decimal_value(tax)
#... some other manipulations
end
def decimal_value(string)
string ? string.gsub(/[^\d\.]/, "") : string
end
end
But, this code is not working as Rails convert the parameters into BigDecimal (I believe it performs to_f to the string). So I am getting NoMethod gsub for BigDecimal when I execute this code. I know I can manipulate the params in the controller itself before saving, or pass the params to a class method in the model and manipulate it there. But, both these options doesnt seem right. Is there anyway, I can manipulate them in the callback itself?
Controller:
def FactsheetsController < ApplicationController
def new
#factsheet = Factsheet.new
end
def create
#factsheet = Factsheet.new(params[:factsheet])
if #factsheet.save
flash[:notice] = "Factsheet created successfully"
redirect_to #factsheet
else
render :action => "new"
end
end
def edit
#factsheet = Factsheet.find(params[:id])
end
def update
#factsheet = Factsheet.find(params[:id])
if #factsheet.update_attributes(params[:factsheet])
flash[:notice] = "Factsheet updated successfully"
redirect_to #factsheet
else
render :action => "edit"
end
end
end
View:
_form.html.erb
# Here user should be able to enter values like $1,000,000.00
# and it should be correctly saved to database as 1000000.0
<%= form.text_field :cam %>
<%= form.text_field :tax %>
You can override the set method of each field in the model, like this:
def shopping_center_size=(num)
self[:shopping_center_size] = decimal_value(num)
end
def cam=(num)
self[:cam] = decimal_value(num)
end
def tax=(num)
self[:tax] = decimal_value(num)
end