我正在使用form_for
和nested_form_fields
在Rails中呈现视图。在此处,@procedure_step
是has_many :procedure_step_actions
的记录,其中每个belongs_to :error
都是ProcedureError
,其中(与某些其他模型的关系中)有一个整数:code
我正试图访问并打印到页面。这是我的模板:
<%= form_for @procedure_step do |f| %>
<%= f.nested_fields_for :procedure_step_actions do |act| %>
<%= act.object.error.code %>
<% end %>
<% end %>
当我运行时,我得到undefined method 'code' for nil:NilClass
。好吧,所以我的关系搞砸了,我无法访问act.object.error
,对吧?更改我的模板以显示它而不是产生#<ProcedureError:0x0000000ece02a8>
,这是人们对功能关系的期望。使用debug
将其内容转储到屏幕上会显示记录的所有属性,包括code
,但我仍然无法使用原始模板访问它!显然act.object.error
不是nil
,因此Rails告诉我act.object.error
是nil
对我没有任何意义。
感到沮丧,我尝试使用act.object.error.to_json
解决问题。这为记录打印了正确的JSON及其所有属性。在JSON.load()
上使用Hash
为我提供了所有属性的正确[:code]
,但使用undefined method '[]' for nil:NilClass
尝试访问代码会给我nil
。同样,我知道对象不是/"code":([0-9]+)/.match(act.object.error.to_json)
,但Rails仍然拒绝允许我访问它。
缺少想法,我尝试使用正则表达式从原始JSON字符串中提取代码。 #<MatchData "\"code\":69" 1:"69">
返回[1]
,这是对的。我使用undefined method '[]' for nil:NilClass
尝试访问匹配的代码,但我又获得了act.object.error_id
。
ActiveRecord足够了,我心想。我决定转向原始SQL查询。我使用"... WHERE id = #{act.object.error_id}"
获取了有问题的错误ID,然后首先将其打印到屏幕上以确保我可以访问它。幸运的是,我可以。然后我用WHERE id =
将其插入到我的SQL查询中。我再次刷新页面,并遇到SQL错误。它显示了我生成的最终SQL查询字符串,但它以ProcedureError.find(action.object.error_id)
结束。错误的ID未添加到字符串中。 ActionBuilder
也犯了类似的错误。
我完全没有想法。什么可能阻止我以这么多不同的方式访问一个简单的整数?
答案 0 :(得分:2)
这里至少有几个问题。首先,如果您使用的是4.x,则可能希望使用fields_for而不是nested_fields_for
。
第二个与第一个答案所表明的相似。你有一个嵌套的字段表单,它允许你嵌套一个级别,但你试图嵌套两个级别。通过解决你的demeter违规法则,你应该能够取得更多的进展。
调试这样的事情,你可以在你的erb中放入binding.pry或byebug权利来获取更多信息。
<%- binding.pry %>
然后重新加载页面。您的服务器将在代码中停止,您可以使用变量值来了解有关正在发生的事情的更多信息。
答案 1 :(得分:1)
我可以立即看到的一件事是你违反了德米特法则
act.object.error.code
表单对象显然必须保留,但您可以通过在procedure_step
上创建一个方法来委托对子对象的访问,这可以帮助处理空值和其他错误情况。
首先尝试委托,因为我不确定nested_forms_for创建的作用域是否允许ActiveRecord :: Relation对象正常执行。我会在当地仔细检查。
代表团可能如下所示
class ProcedureStepActions
belongs_to :error
def error_code
@error.code
end
end
编辑:
其他可能有用的东西是您正在使用的Ruby和Rails的版本以及任何其他额外的宝石或库。