Simon
Simon

Reputation: 950

Determining the correct usage of named yield with content_for

I have a lot of shared code for several different forms, and am trying to use a named yield. I want _nav.html.haml to render the form with the field for each page defined in a content_for block.

Example view:

- content_for :form_fields do
  = f.text_field :name
  = f.text_field :number

= render :layout => 'projects/shared/nav', locals: {:url => projects_path, :form => @form}

Contents of _nav:

 = form_for(form, url: url, layout: :horizontal) do |f|
   = f.alert_message "Please fix the errors below before saving this page."
   = yield :form_fields

I'm getting the following error in the example view:

undefined local variable or method `f'

Upvotes: 1

Views: 517

Answers (2)

Kamesh
Kamesh

Reputation: 1465

You are not passing the form object to the content_for. That's why it is displaying an error.

Unfortunately, you can't pass any argument to content_for except the name and block.

=> yield(:block_name, form_object)
ArgumentError: wrong number of arguments (2 for 0..1)
from /test/.rvm/gems/ruby-2.1.5/gems/actionpack-4.0.2/lib/action_view/context.rb:31:in `_layout_for'

The method which renders the content_for view takes only the name of the block. check it here. http://www.rubydoc.info/docs/rails/4.1.7/ActionView/Context:_layout_for

You are not supposed to use content_for here. The correct solution here is "Partials"

http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

Upvotes: 1

Simon
Simon

Reputation: 950

After difficulty in getting the form passed to the content_for block, I ended up removing the content_for and rearranging my code like so:

= render :layout => 'projects/shared/nav', locals: {:url => projects_path, :form => @form} do
  = @f.text_field :name
  = @f.text_field :number

And the yield like so:

= form_for(form, url: url, layout: :horizontal) do |f|
    - @f = f
    = f.alert_message "Please fix the errors below before saving this page."
    = yield

It feels a bit messy but I couldn't work out another way to pass the form around, works as expected.

Upvotes: 0

Related Questions