我使用单表继承来管理不同类型的项目。
型号:
class Project < ActiveRecord::Base
end
class SiteDesign < Project
end
class TechDesign < Project
end
从projects_controller编辑动作:
def edit
@project = Project.find(params[:id])
end
查看edit.html.erb:
<% form_for(@project, :url => {:controller => "projects",:action => "update"}) do |f| %>
...
<%= submit_tag 'Update' %>
<% end %>
更新projects_controller的操作:
def update
@project = Project.find(params[:id])
respond_to do |format|
if @project.update_attributes(params[:project])
@project.type = params[:project][:type]
@project.save
flash[:notice] = 'Project was successfully updated.'
format.html { redirect_to(@project) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
end
end
end
然后我在编辑视图上对TechDesign条目进行了一些编辑并得到错误:
NoMethodError in ProjectsController#update
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
在参数中很明显,我没有项目参数名称,而是有tech_design 参数:
{"commit"=>"Update",
"_method"=>"put",
"authenticity_token"=>"pd9Mf7VBw+dv9MGWphe6BYwGDRJHEJ1x0RrG9hzirs8=",
"id"=>"15",
"tech_design"=>{"name"=>"ech",
"concept"=>"efds",
"type"=>"TechDesign",
"client_id"=>"41",
"description"=>"tech"}}
如何解决?
答案 0 :(得分:26)
这是您问题的根源。这是将@project设置为TechDesign对象的实例。
def edit
@project = Project.find(params[:id])
end
您可以通过在form_for调用中指定名称项目来确保事情按您所需的方式工作。
<% form_for(:project, @project, :url => {:controller => "projects",:action => "update"}) do |f| %>
...
<%= submit_tag 'Update' %>
<% end %>
答案 1 :(得分:6)
对于Rails 3
<% form_for(@project, :as => :project, :url => {:controller => "projects",:action => "update"}) do |f| %>
...
<%= submit_tag 'Update' %>
<% end %>
答案 2 :(得分:2)
随机说明:如果您正在使用单表继承(STI)并忘记从子类定义中删除 initialize 方法,那么当您没有预期时,您将获得类似的“nil对象” “例外。
例如:
class Parent < ActiveRecord::Base
end
class Child < Parent
def initialize
# you MUST call *super* here or get rid of the initialize block
end
end
就我而言,我使用IDE创建子类,IDE创建了initialize方法。让我永远追踪......
答案 3 :(得分:2)
对于Rails 4,我已经确认对我来说唯一有效的方法是明确指定URL和AS参数:
<% form_for(@project, as: :project, url: {controller: :projects, action: :update}) do |f| %>
...
<% end %>
对我来说似乎很难看!