Reputation: 469
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!
Upvotes: 2
Views: 599
Reputation: 240
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
Upvotes: 0
Reputation: 1545
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}
Upvotes: 3
Reputation: 9649
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!
Upvotes: 0