I am new to rails and am in the process of entering in information in a form and saving it to a database. I am following a tutorial which may be out of date. I am getting an error on the second line. Am I passing the wrong parameter?
def create
#student = Student.new(params[:student])
if #student.save
redirect_to new_student_path
end
end
I expect the problem is that you need to process the student parameters before passing them to Student.new, so as not to fall foul of the strong parameters system.
Try this:
def create
#student = Student.new(student_parameters)
if #student.save
redirect_to new_student_path
end
end
private
def student_parameters
params.require(:student).permit(:name, :age)
end
replace :name, :age with the list of attributes you want to white list (allow through)
More information about the mass assignment vulnerability that strong parameters mitigates can be found here.
Related
Here i'm trying to save json data to sqlite database using rails controller, but i'm not getting json data to controller parameters
In a specific controller I have the below list of params:
Parameters: {"person"=>"{\"name\":\"akhil\",\"profession\":\"it\",\"address\":\"hyderabad\",\"mobilenum\":67588}"}
Controller
def createPerson
puts "parameters are : "+params[:person].to_s
user_params = ActiveSupport::JSON.decode(params[:person])
puts "parameters name:"+user_params[:name].to_s
#person = Person.new(name: user_params[:name], profession:
user_params[:profession], address: user_params[:address], mobilenum:
user_params[:mobilenum])
#person.save
end
It is showing below error
(no implicit conversion of nil into String)
I'm getting the nil value in user_params[:name].to_s
Could you please help me to solve this
Seems like all you need to do is to create a new Person record after submitting a form. Well, probably you would want to use strong params and make a little refactor, so your controller will look something like this:
class PersonsController < ApplicationController
# you can name your action simply `create`, so you can use resource routing
def create
# most probably you don't need to make person an instance variable
person = Person.new(person_params)
# and here it is a good practice to check if you really saved your person
if person.save
# do something to tell user that the record is saved, e.g.
flash[:success] = 'person has been saved'
else
# show user why your person record is not saved, e.g.
flash[:error] = "person cannot be saved: #{person.errors.full_messages.to_sentence}"
end
end
private
# and here is the method for your permissible parameters
def person_params
params.require(:person).permit(:name, :profession, :address, :mobilenum)
end
end
I have an update method right now that will not work for all situations. It is hard coded in the strong params like this params.require(:integration_webhook).permit(:filters) that all fine right now but sometimes it may be integration_webhook and other times it needs to be integration_slack. Basically, is there a way that I don't need to hardcode the require in the strong params? I'll show my code for clarity.
Update Method:
def update
#integration = current_account.integrations.find(params[:id])
attrs = params.require(:integration_webhook).permit(:filters)
if #integration.update_attributes(attrs)
flash[:success] = "Filters added"
redirect_to account_integrations_path
else
render :filters
end
end
As you can see it's a standard update method. But I need the integration_webhook params to be dynamic. I'm wondering if there is a model method I could call to strip away the integration_webhook part?
Not totally sure how dynamic this needs to be, but assuming that we are either getting an integratino_webhook or a integration_slack.
def update
#integration = current_account.integrations.find(params[:id])
if #integration.update_attributes(update_params)
# ...
else
# ...
end
end
private
def update_params
params.require(:integration_webhook).permit(:filters) if params.has_key?(:integration_webhook)
params.require(:integration_slack).permit(:filters) if params.has_key?(:integration_slack)
end
Checkout Strong parameters require multiple if this didn't answer your question.
Edit
For more dynamic requiring:
def update_params
[:integration_webhook, :integration_slack].each do |model|
return params.require(model).permit(:filters) if params.has_key?(model)
end
end
Off the top of my head something like this should work. The naming convention isn't the best but it the structure will allow you to just add to the list if you need to.
def update
#integration = current_account.integrations.find(params[:id])
if #integration.update_attributes(webhook_and_slack_params)
flash[:success] = "Filters added"
redirect_to account_integrations_path
else
render :filters
end
end
def webhook_and_slack_params
[:integration_webhook, :integration_slack].each do |the_params|
if(params.has_key?(the_params))
params.require(the_params).permit(:filters)
end
end
I'm trying to create and order that is associated with an item.
An Order has one item:
class Order < ActiveRecord::Base
has_one :item
end
An Item belongs to an order:
class Item < ActiveRecord::Base
belongs_to :user
end
According to the guide this should work:
build_association(attributes = {})
create_association(attributes = {})
I have this in my controller:
def create
#order = #current_item.build_order(order_params)
#order.save
redirect_to #order
end
And this is the error I'm getting:
undefined method `build_order' for nil:NilClass
I know this has to do with how I've defined current_items but I've tried many different things and all lead to this same error message.
I have this in my application helper:
def current_item
Item.find(params[:id])
end
Can anyone point me in a better direction for how to define this or what I'm doing wrong here. Thanks for your help!
1) You don't have access to a helper method from the controller. You can include the helper class in your controller but it's a really bad practice. You must use helper methods only in the views.
2) You can move current_item method from the helper to the controller. Then there will be another problem. In your create method, you are trying to access instance variable #current_item which is not initialized at the moment, not the method. You can do it this way:
#order = #current_item.build_order(order_params)
to
#order = current_item.build_order(order_params)
Then current_item will return you Item object.
3) I am not sure what are your params, but you can implement it this way:
def create
#order = Order.new(params[:order])
#order.save
redirect_to #order
end
where params[:order] is for example:
{name: "order 1", item_id: 1}
You should change your create to use a method, rather a variable, so modify it as follows:
def create
#order = current_item.build_order(order_params)
#order.save
redirect_to #order
end
# rest of code
def current_item
Item.find(params[:id])
end
This should help.
Good luck!
The error you're getting is being caused by trying to run Item.find(params[:id]) but not passing it a valid value. It seems that params[:id] is maybe nil? Can you confirm this using a debugger or by temporarily adding raise "Params[:id] is set to #{params[:id]} to the first line of the method, running the code and seeing what it says in the terminal output?
All you need to do make this work is have a parameter value for the item come from the form that is being submitted. Normally rails uses the route/url to populate the value of params[:id]. For example, when the request is GET /items/1, params[:id] is 1.
In this case though, unless you've done some custom routing that you haven't shown in your question, creating a new order would usually be a POST to /orders and since there is no id in the url, params[:id] is nil.
It's up to you to add the item id from the order form. It would make sense that it would be sent with the rest of the order params as item_id, rather than just id, since id is usually used to reference the current object, which is a new order and therefore doesn't get have an id.
You'll need to make sure that item_id is whitelisted in your strong params with the rest of the values in the order_params method (I assume you defined this in the same controller but did not show it in the code), and then the code would look something like this.
def create
#order = current_item.build_order(order_params)
#order.save
redirect_to #order
end
#note the changes the the argument
def current_item
Item.find(order_params[:item_id])
end
def order_params
params.require(:order).permit(:item_id, :other_values_that_you_send)
end
I am rather new to rails and programming in general. I feel I have picked up the rails MVC and other concepts pretty well but still have a hard time figuring out the syntax of what goes into controller actions. For example when you create a
def edit
end
How do you know how to format the contents/inside of that method.
Thus far I have seen alot of this:
def new
#product = Product.new
end
If I understand this correctly this is creating an instance of the Product Model and putting it into an instance variable that is accessible by the "new" view in products/view
But let's say I want to edit that. My inclination is to do add the following action in the controller:
def edit
#product = Product.edit
end
I'm not sure the syntax Product.edit is correct though, not sure how to differentiate between edit and update either. How do I know what calls on my Model Object when creating instance variables? Is there somewhere online I can go to learn this? I have found no where thus far with a good list of commands I can play with.
def edit
#product = Product.edit
end
should be
def edit
#product = Product.find(params[:id])
end
simple explanation
The edit action (#method) is called when you call e.q localhost:3000/products/1/edit
the 1 is the id of your product which is passed to your controller and can be accessed by using params.
when the user hit edit . It is ussually send the data to update action
def update
#product = Product.find(params[:id])
#product.update(params[:product].permit(:title, :desc))
end
Ok i know i'm not explain it good enough. You really need to read this
http://guides.rubyonrails.org/
To edit something, first you need to have (or get, or create, or etc...) it. In the new method, you just create new instance of Product, this is not necessary, but needs for *form_for* helper, and generally good practice, because it you can use same form for creating and editing. Product.new just creates new product and initialize its fields with default values. Product.find searches product (single) in database by id and returns it. So for editing you first need to find your product, then it will be used to fill fields in editing form, and than in update method you will update it:
def update
target_product_required
#product.assign_attributes(product_params)
if #product.save
redirect_to #product
else
render :edit
end
end
def target_product_required
#product ||= Product.find(params[:id])
end
def product_params
params.require(:product).permit(:title, :description, :price, :available_quantity, :image, :remote_image_url)
end
This is common pattern: target_product_required returns/assigns founded by id in params product to instance variable, product_params returns product specified params. More about this read in http://guides.rubyonrails.org/
I currently have two models School and Course where School has_many courses, and Course belongs_to school. Additionally, School and Course are nested resources, where School is the parent resource, and Course the child.
I have created several test records in the Rails Console so that a query such as when the child calls upon the parent Course.first.school successfully executes and returns all the relevant information of the school Course.first is associated with.
However, when put into a controller function, I would instead get an error "undefined method `school' for nil:NilClass" for the following line:
redirect_to school_course_path(#course.school, #course)
.. as if the .school part wasn't recognized (where as it was in the console). Why is this the case, and how do I get past this error? Thanks!
Edit - as suggested, it could be that my #course instance variable isn't passed from method to method in the controller. I have attempted at passing them through via a private method, but its still giving me the same error. Here is my code (background: the model Question belongs_to Course, with Course having many questions. Course isn't part of the nested routes)
class QuestionsController < ApplicationController
def new
#course = Course.find(params[:course]) #confirmed working
self.current_course = #course #I attempt to set current_course, a private method
#question = Question.new
end
def create
#question = Question.new(params[:question]) #also works, in rails console all the questions confirms to have rails id
if #question.save
redirect_to school_course_path(current_course.school, current_course) #source of my frustrations - continues to returns same error message
else
render 'new'
end
end
private
def current_course=(course)
#current_school = course
end
def current_course
#current_course
end
end
Should work if your relationships are set up the way I think they are:
def create
#question = Question.new(params[:question])
#course = #question.course
if #question.save
redirect_to school_course_path(#course.school, #course)
else
render 'new'
end
end
Make sure you have something like this in your create action:
#course = Course.new(params[:course])
your code is okay, it seems there is problem in your redirect.. redirect it to root_path and check whether it is working??