创建has_one关联错误Rails 4

时间:2015-04-11 16:07:14

标签: ruby-on-rails ruby ruby-on-rails-4

我正在尝试创建与订单相关联的订单。

订单有一个项目:

class Order < ActiveRecord::Base
    has_one :item
end

物品属于订单:

class Item < ActiveRecord::Base
  belongs_to :user 
end 

根据指南,这应该有效:

build_association(attributes = {})
create_association(attributes = {})

我在控制器中有这个:

def create
    @order = @current_item.build_order(order_params)
    @order.save
    redirect_to @order
end 

这就是我得到的错误:

未定义的方法`build_order&#39;为零:NilClass

我知道这与我如何定义current_items有关,但我尝试过很多不同的事情,所有这些都会导致同样的错误信息。

我在我的应用程序助手中有这个:

def current_item
   Item.find(params[:id])
end

任何人都可以指出我如何定义这个或我在这里做错了什么更好的方向。谢谢你的帮助!

3 个答案:

答案 0 :(得分:3)

1)您无法从控制器访问辅助方法。您可以在控制器中包含帮助程序类,但这是一个非常糟糕的做法。您必须仅在视图中使用辅助方法。

2)您可以将current_item方法从帮助程序移动到控制器。然后会有另一个问题。在create方法中,您尝试访问此时未初始化的实例变量@current_item,而不是方法。你可以这样做:

@order = @current_item.build_order(order_params)

@order = current_item.build_order(order_params)

然后current_item将返回Item对象。

3)我不确定你的参数是什么,但你可以这样实现:

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

其中params [:order]例如:

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

答案 1 :(得分:0)

您应该更改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

这应该有所帮助。

祝你好运!

答案 2 :(得分:0)

您获得的错误是由于尝试运行Item.find(params[:id])但未向其传递有效值而导致的。似乎params [:id]可能是零?您可以使用调试器或临时将raise "Params[:id] is set to #{params[:id]}添加到方法的第一行,运行代码并查看它在终端输出中的内容来确认这一点吗?

您需要做的就是让项目的参数值来自正在提交的表单。通常rails使用route / url来填充params [:id]的值。例如,当请求为GET /items/1时,params [:id]为1.

在这种情况下,除非您已经完成了一些未在问题中显示的自定义路由,否则创建新订单通常是对/ orders的POST,因为url中没有id,params [ :id]为零。

您可以在订单表单中添加商品ID。因为item_id通常用于引用当前对象,因此它将与其余的订单参数id一起发送,而不仅仅是id。新订单,因此没有id。

你需要确保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