开发者

How do I update two models with one form in Ruby on Rails?

I have two models, Page and PageContent.

class Page < ActiveRecord::Base
  has_many :page_contents
end

class PageContent < ActiveRecord::Base
  belongs_to :page
end

Page has a :css_design attribute, but I want to be able to edit that attribute from my PageContent 开发者_开发技巧form. Any ideas?

I see a lot of accepts_nested_attributes and fields_for advice, but they don't work, because they all seem to be for forms that are either A. Creating entire new instances of a different model from a form (for example, creating tasks from a project form), or B. Updating associated records thru the parent. I want to do the opposite- I want to update the parent's record thru associated records.

Any help is greatly appreciated! Many thanks in advance!

--Mark


UPDATE


I have added the following to my PageContent model:

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

And I have, in both my create and update actions:

@page_content.update_attributes params[:page_content]

But I'm getting:

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'

When I go to create the page_content for the first time. I copied and pasted this stuff straight from my files, so if you see anything weird, please let me know!


Update your model with the following:

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

Your form can now display and update the current Page's value, even though it looks like it's only handling PageContent:

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

In your controller, e.g.:

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


If it's not too many fields, you can add attributes to the PageContent model via attr_accessor. Then update the parent after_save. Something like this:

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

Then you can put a form field for it just like any other PageContent field. If it's more than one field, use update_attributes. Also, you probably want to make sure the attribute is set (using attribute_present?(attribute)) so it doesn't overwrite it with nil.

(Sorry I don't have time to test it right away. I'll try later. )

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜