0

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!

1
  • FWIW, I would have expected accepts_nested_attributes_for to have worked here, but there are a couple of other solutions below worth exploring... Commented May 11, 2011 at 6:01

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Jeremy, when I've tried to get this running, it's working in existing pages (for editing), but not in creating a new PageContent. The specific error I'm getting is: NoMethodError in Page_contents#new Any hints to point me in the right direction would be greatly appreciated!
Mark, I've edited my answer with code that will gracefully handle no Page association.
Thanks Jeremy, I'm now getting an error upon submitting the PageContent form: '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'
My PageContent model has the following in it: 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
1

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. )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.