STI 和 form_for 问题

发布于 2024-08-08 04:50:20 字数 1721 浏览 8 评论 0原文

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

模型:

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.[]

在parameters中,很明显,我有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"}}

如何修复?

I am using Single Table Inheritance for managing different types of projects.

Models:

class Project < ActiveRecord::Base
end

class SiteDesign < Project
end

class TechDesign < Project
end

Edit action from projects_controller:

def edit
   @project = Project.find(params[:id])
end

View edit.html.erb:

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

Update action of 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

Then i do some edits of TechDesign entry on edit view and get error:

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.[]

In parametrs it is obvious that instead of project parameter name i have tech_design
Parameters:

{"commit"=>"Update",
 "_method"=>"put",
 "authenticity_token"=>"pd9Mf7VBw+dv9MGWphe6BYwGDRJHEJ1x0RrG9hzirs8=",
 "id"=>"15",
 "tech_design"=>{"name"=>"ech",
 "concept"=>"efds",
 "type"=>"TechDesign",
 "client_id"=>"41",
 "description"=>"tech"}}

How to fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不甘平庸 2024-08-15 04:50:20

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

def edit
   @project = Project.find(params[:id])
end

您可以通过在 form_for 调用中指定 :project 作为名称来确保事情按照您想要的方式工作。

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

Here's the source of your problem. This is setting @project as an instance of a TechDesign object.

def edit
   @project = Project.find(params[:id])
end

You can ensure things work the way you want by specifying :project for a name in the form_for call.

<% form_for(:project, @project, :url => {:controller => "projects",:action => "update"}) do |f| %>
    ...
    <%= submit_tag 'Update' %>
<% end %>
只有影子陪我不离不弃 2024-08-15 04:50:20

对于 Rails 3

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

For Rails 3

<% form_for(@project, :as => :project, :url => {:controller => "projects",:action => "update"}) do |f| %>
...
   <%= submit_tag 'Update' %>
<% end %>
傾旎 2024-08-15 04:50:20

随机提示:如果您使用单表继承 (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 创建了初始化方法。我花了很长时间才找到...

A random note: If you are using single table inheritance (STI) and forget to remove the initialize method from your subclass definitions you will get a similar "nil object when you didn't expect it" exception.

For example:

class Parent < ActiveRecord::Base
end

class Child < Parent
  def initialize
    # you MUST call *super* here or get rid of the initialize block
  end
end

In my case, I used my IDE to create the child classes and the IDE created the initialize method. Took me forever to track down...

从此见与不见 2024-08-15 04:50:20

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

<% form_for(@project, as: :project, url: {controller: :projects, action: :update}) do |f| %>
    ...
<% end %>

对我来说似乎很难看!

For Rails 4, I have confirmed the only thing that has seemed to work for me is to explicitly specify the URL and the AS parameters:

<% form_for(@project, as: :project, url: {controller: :projects, action: :update}) do |f| %>
    ...
<% end %>

Seems ugly to me!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文