简体   繁体   English

创建has_one关联错误Rails 4

[英]creating has_one association error Rails 4

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 nil:NilClass的未定义方法“ build_order”

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. 我知道这与我定义current_items的方式有关,但是我尝试了许多不同的方法,并且都导致了相同的错误消息。

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. 1)您无权从控制器访问帮助方法。 You can include the helper class in your controller but it's a really bad practice. 您可以在控制器中包括helper类,但这是一个非常糟糕的做法。 You must use helper methods only in the views. 您只能在视图中使用辅助方法。

2) You can move current_item method from the helper to the controller. 2)您可以将current_item方法从帮助器移动到控制器。 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. 在您的create方法中,您尝试访问的实例变量@current_item目前尚未初始化,而不是方法。 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. 然后current_item将返回您的Item对象。

3) I am not sure what are your params, but you can implement it this way: 3)我不确定您的参数是什么,但是您可以通过以下方式实现它:

def create
  @order = Order.new(params[:order])
  @order.save
  redirect_to @order
end

where params[:order] is for example: 其中params [:order]例如:

{name: "order 1", item_id: 1}

You should change your create to use a method, rather a variable, so modify it as follows: 您应该将create更改为使用方法而不是变量,因此,请按以下方式进行修改:

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. 您收到的错误是由于尝试运行Item.find(params[:id])但未传递有效值引起的。 It seems that params[:id] is maybe nil? 似乎params [:id]可能为零? 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? 您是否可以使用调试器或通过在方法的第一行中临时添加raise "Params[:id] is set to #{params[:id]} ”,运行代码并查看其在终端输出中的内容来确认这一点?

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]. 通常,rails使用route / url来填充params [:id]的值。 For example, when the request is GET /items/1 , params[:id] is 1. 例如,当请求为GET /items/1 ,params [:id]为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. 不过,在这种情况下,除非您做了一些未在问题中显示的自定义路由,否则创建新订单通常是对/ orders的POST,并且由于url中没有id,因此params [:id]是零。

It's up to you to add the item id from the order form. 您可以从订单中添加商品ID。 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. 这将是有意义的,它将与其余订单参数一起作为item_id ,而不是仅与id ,因为id通常用于引用当前对象,这是一个新订单,因此没有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. 您需要确保将您的强参数中的item_id与order_params方法中的其余值一起列入白名单(我假设您是在同一控制器中定义的,但未在代码中显示),然后代码将看起来像这样。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM