Ruby on rails 问题的STI和form_

Ruby on rails 问题的STI和form_,ruby-on-rails,form-for,sti,Ruby On Rails,Form For,Sti,我使用单表继承来管理不同类型的项目 型号: class Project < ActiveRecord::Base end class SiteDesign < Project end class TechDesign < Project end 查看edit.html.erb: <% form_for(@project, :url => {:controller => "projects",:action => "update"}) do |f|

我使用单表继承来管理不同类型的项目

型号:

class Project < ActiveRecord::Base
end

class SiteDesign < Project
end

class TechDesign < Project
end
查看edit.html.erb:

<% form_for(@project, :url => {:controller => "projects",:action => "update"}) do |f| %>
    ...
    <%= submit_tag 'Update' %>
<% 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.[]
在参数中,很明显,我使用的不是项目参数名称,而是技术设计 参数:

{"commit"=>"Update",
 "_method"=>"put",
 "authenticity_token"=>"pd9Mf7VBw+dv9MGWphe6BYwGDRJHEJ1x0RrG9hzirs8=",
 "id"=>"15",
 "tech_design"=>{"name"=>"ech",
 "concept"=>"efds",
 "type"=>"TechDesign",
 "client_id"=>"41",
 "description"=>"tech"}}
<% form_for(@project, as: :project, url: {controller: :projects, action: :update}) do |f| %>
    ...
<% end %>

如何修复它?

这是问题的根源。这是将@project设置为TechDesign对象的实例

def edit
   @project = Project.find(params[:id])
end
您可以通过指定:project作为形式为_forcall的名称来确保事情按您想要的方式进行

<% form_for(:project, @project, :url => {:controller => "projects",:action => "update"}) do |f| %>
    ...
    <%= submit_tag 'Update' %>
<% end %>
{:controller=>“projects”,:action=>“update”})do | f |%>
...

随机提示:如果您使用单表继承(STI)并忘记从子类定义中删除initialize方法,您将得到类似的“nil object when you not expected”异常

例如:

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方法。我花了很长时间才找到Rails 3的…

<% form_for(@project, :as => :project, :url => {:controller => "projects",:action => "update"}) do |f| %>
...
   <%= submit_tag 'Update' %>
<% end %>
:project,:url=>{:controller=>“projects”,:action=>“update”})do | f |%>
...

对于Rails 4,我已经确认唯一对我有效的方法是显式指定URL和AS参数:

{"commit"=>"Update",
 "_method"=>"put",
 "authenticity_token"=>"pd9Mf7VBw+dv9MGWphe6BYwGDRJHEJ1x0RrG9hzirs8=",
 "id"=>"15",
 "tech_design"=>{"name"=>"ech",
 "concept"=>"efds",
 "type"=>"TechDesign",
 "client_id"=>"41",
 "description"=>"tech"}}
<% form_for(@project, as: :project, url: {controller: :projects, action: :update}) do |f| %>
    ...
<% end %>

...

我觉得很难看

谢谢你的回复。在这些更改之后,我得到了这个错误:1没有响应任何操作。操作:添加此映射后创建、销毁、编辑、索引、新建、显示和更新。连接“projects/:id/edit”、:controller=>“projects”、:action=>“edit”到routes.rb错误已消除。问题是,如果map.resources:projects已经出现在routes中,为什么没有它就不能工作呢?在Rails 3.1中,将语句的形式_写为:project do | f |%>旧线程,但因为我在谷歌搜索时发现了它,所以我就是这么做的:注意,
:as=>:project
只会影响参数,而不会影响URL。