如何在Ruby on Rails中使用一个表单更新两个模型?

时间:2011-05-11 01:35:39

标签: ruby-on-rails database forms activerecord

我有两个模型,Page和PageContent。

class Page < ActiveRecord::Base
  has_many :page_contents
end

class PageContent < ActiveRecord::Base
  belongs_to :page
end

Page有一个:css_design属性,但我希望能够从我的PageContent表单中编辑该属性。有任何想法吗?

我看到了很多 accepts_nested_attributes fields_for 建议,但是无法正常工作,因为它们似乎都适用于要么是A.从表单创建不同模型的全新实例(例如,从项目表单创建任务),或B.通过父级更新关联记录。 我想做相反的事情 - 我想通过相关记录更新父记录。

非常感谢任何帮助!非常感谢提前!

- 标记


更新


我已将以下内容添加到我的PageContent模型中:

def css_design
    page ? page.css_design : nil
  end

  def css_design= (val)
    if page
      page.update_attribute 'css_design', val
    else
      @css_design = val
    end
  end

  after_create :set_page_css_design_on_create
  def set_page_css_design_on_create
    self.css_design = @css_design if page && @css_design
  end

我在创建和更新操作中都有:

@page_content.update_attributes params[:page_content]

但我得到了:

NoMethodError (undefined method `css_design=' for #<Page:0x00000003a80338>):
  app/models/page_content.rb:13:in `css_design='
  app/controllers/page_contents_controller.rb:56:in `new'
  app/controllers/page_contents_controller.rb:56:in `create'

当我第一次创建page_content时。我直接从我的文件中复制并粘贴了这些东西,所以如果你看到任何奇怪的东西,请告诉我!

2 个答案:

答案 0 :(得分:1)

如果字段不是太多,您可以通过attr_accessor向PageContent模型添加属性。然后更新父After_save。像这样:

class PageContent < ActiveRecord::Base
  belongs_to :page

  attr_accessor :css_design

  after_save :update_parent_css

  private

    def update_parent_css
      self.page.update_attribute(:css_design, self.css_design)
    end

end

然后,您可以为其添加表单字段,就像任何其他PageContent字段一样。如果它不止一个字段,请使用update_attributes。此外,您可能希望确保设置属性(使用attribute_present?(attribute)),因此它不会用nil覆盖它。

(抱歉,我没有时间立即测试。我会稍后再试。)

答案 1 :(得分:1)

使用以下内容更新您的模型:

class PageContent < ActiveRecord::Base
  belongs_to :page
  def css_design
    page ? page.css_design : nil
  end
  def css_design= (val)
    if page
      page.update_attribute 'css_design', val
    else
      @css_design = val
    end
  end
  after_create :set_page_css_design_on_create
  def set_page_css_design_on_create
    self.css_design = @css_design if page && @css_design
  end
end

您的表单现在可以显示并更新当前页面的值,即使它看起来只是处理PageContent:

<%= form_for @page_content do |f| %>
  ...
  <%= f.text_field :css_design %>
  ...
<% end %>

在您的控制器中,例如:

def update
  ...
  @page_content.update_attributes params[:page_content]
  ...
end