编辑:事实证明我犯了一个非常简单的错误,并且有一个与不再存在的LocalTemplate id相关联的模板。如果有人遇到此问题,并认为他们无法在更新操作中无法将另一个模型的ID关联,请确保您没有意外删除导致该ID不再存在的父对象! 下面的代码,虽然大大简化,但对我来说很有用。
我的rails应用程序中有一个模板模型。它有一个方法"数据"在其中定义。
我可以使用@ template.data在create和show actions中访问此方法,但是当在我的控制器的更新操作中使用相同的@ template.data时,我得到一个no方法错误,因为我没有显示更正本地模板ID。此行可在模型中找到,其中显示base_data = YAML.load(local_template.data)
我在最初保存新模板时存储了关联local_template的id,但是如何确保在更新操作中再次引用该id,这样我就不会出现no方法错误?
这是模板模型和控制器的简化版本
型号:
class Template < ActiveRecord::Base
def data
base_data = YAML.load(local_template.data)
# couldn't pass the correct LocalTemplate here because
# the local_template_id I had in my Template model no
# longer existed. Changing the id to a LocalTemplate
# that did exist fixed the issue.
end
end
控制器:
class TemplatesController < ApplicationController
def index
@business = Business.find(params[:business_id])
@templates = @business.templates.all
end
def new
@business = Business.find(params[:business_id])
@local_templates = LocalTemplate.all
@template = @business.templates.build
end
def create
@business = Business.find(params[:business_id])
@local_templates = LocalTemplate.all
@template = @business.templates.build(template_params)
if @template.save
@template.data #works fine here
redirect_to business_url(@template.business_id)
else
render 'new'
end
end
def show
@business = Business.find(params[:business_id])
@template = @business.templates.find(params[:id])
@template.data #works fine here too
end
def edit
@business = Business.find(params[:business_id])
@local_templates = LocalTemplate.all
@template = @business.templates.find(params[:id])
end
def update
@business = Business.find(params[:business_id])
@template = @business.templates.find(params[:id])
if @template.update_attributes!(pass_template_params)
Api.new.update_template(@template.data.to_json) #this is where I had a problem
redirect_to business_url(@template.business_id)
else
render 'edit'
end
end
end
答案 0 :(得分:1)
你混合了很多。您的控制器中有很多重构...
首先,您的TemplatesController应该与模板资源有关,但您的控制器看起来更像是BusinessesController。通常,您的更新操作应该更像是:
def update
@template = Template.find params[:id]
@template.attributes = template_params # though this should raise a NoMethodError, because you dind't define it; I'd prefer params[:template] if possible
if @template.save
redirect_to business_url(@template.business_id)
else
@local_templates = LocalTemplate.all
render 'edit'
end
end
实例化@business和@local_templates没有意义,因为你根本不使用它。如果可以的话,加快你的反应! :)
修复了更新中不需要嵌套资源的开销(正如您所做的那样)
如果由于验证原因而导致保存@template失败,则最好通过以下方式加载业务对象:
@template.business
在/templates/edit.html.erb部分中。那么你也不需要一个嵌套的路线来编辑动作...你看,它清理了很多 作为一般准则,您应该尽可能少地创建控制器实例变量 如果您清理了控制器和视图,则可以更轻松地调试数据问题 我假设:
local_template
模板模型中的是关联的LocalTemplate模型对象。因此,如果确保引用的对象存在,那么在任何地方调用它应该没有问题:
class Template < ActiveRecord::Base
def data
return if local_template.nil?
YAML.load(local_template.data)
end
end
或验证local_template对象的存在。甚至b
答案 1 :(得分:0)
你应该确认@template不是nil,如果@template为nil,你就不能使用数据方法。
1.9.3-p547 :024 > nil.data
NoMethodError: undefined method `data' for nil:NilClass
from (irb):24
from /Users/tap4fun/.rvm/rubies/ruby-1.9.3-p547/bin/irb:12:in `<main>'
你应该使用 update_attributes!,如果记录无效,它可以引发异常。
你可以这样做。
if @template
@template.update_attributes!(template_params)
@template.data
end