0

I have a rails 4 app that has a form that looks like:

<%= form_for @store, :html => {:multipart => true} do |f| %>
  <%= f.fields_for :products do |product| %>
    <%= render partial: "edit_product_fields", locals: {product:product} %>
  <% end %>
  <%= f.submit %>
<% end %>

and the edit_product_fields partial looks like:

<select>
   <option value="Textbook" <% if product.type_of == "Textbook" %>selected<% end %>>Textbook</option>
   <option value="Magazine" <% if product.type_of == "Magazine" %>selected<% end %>>Magazine</option>
   <option value="Book"     <% if product.type_of == "Book"     %>selected<% end %>>Book</option>
</select>

When I have the code like this, I get the error:

undefined method `type_of' for #<NestedForm::Builder:0x00000102304f78>

but if I change the render line to (I just made it less explicit by taking out partial:):

<%= render "edit_product_fields", locals: {product:product} %>

I get the error:

undefined local variable or method `product' for #<#<Class:0x0000010235a248>:0x0000010684b3c0>
3
  • 1
    I wonder how well is this gem maintained. last time I tried using nested_form, it didn't work for me. So I opted for cocoon gem Commented May 30, 2014 at 0:19
  • @WaliAli I don't think the OP is referring to a gem here, just the concept of nested attributes. Commented May 30, 2014 at 0:40
  • @pdobb you are probably right. Commented May 30, 2014 at 1:19

2 Answers 2

2

In your first code block, you have a Builder object being stored as product.

Fortunately, Builder provides an object method so you can access the actual object that it's representing in the form:

<select>
   <option value="Textbook" <%= 'selected' if product.object.type_of == "Textbook" %>>Textbook</option>
   <option value="Magazine" <%= 'selected' if product.object.type_of == "Magazine" %>>Magazine</option>
   <option value="Book"     <%= 'selected' if product.object.type_of == "Book"     %>>Book</option>
</select>
Sign up to request clarification or add additional context in comments.

4 Comments

thanks for the response. I tried this, but got undefined method type_of for #<Class:0x000001064bcf60>
As I pointed out, try product.object.class.name or product.object.is_a? Textbook instead of type_of. I'm not even sure if type_of exists in Ruby or Rails.
Oops, I should have read better, sorry. type_of is a field in my product model. This code doesn't give me an error, but for the select I'm trying to say "If product.type_of is equal to Textbook, then make it selected". I should have been more clear, sorry about that.
No problem. I thought you were trying to mix JavaScript typeof with Ruby somehow. :)
2

Well type_of is not a ruby method. It looks like it's an attempt to type check though... But type checking is generally frowned upon in duck-typed languages. At any rate, we can take advantage of a Rails Form Helper instead and make this code a one-liner. But first...

The reason the render is complaining about undefined local variable or methodproduct'` after your change is because the render call expects either the first argument to be a partial name and the second to be a hash of locals:

<%= render "partial_name", local1: "a", local2: "b" %>

... or it expects the the whole thing to be a hash:

<%= render partial: "partial_name", locals: { local1: "a", local2: "b" } %>

Now, back to the form helper.

What you're looking for here is the select helper. This makes the following possible:

<%= product.select :type_of, %w[Textbook Magazine Book] %>

And this will render all of the same html as you've put into your _edit_product_field.html.erb partial. So you should probably just get rid of the partial to save on rendering time and put this directly into your form.

One other, minor point. It may be less confusing to call the fields_for block variable product_form instead of product. This is to help keep in mind that this is not a Product object you're dealing with, but rather a Form Generator object. Also, you don't need to specify :multipart => true in Rails 4 forms -- Rails knows to make the form multi-part if you have a file upload element within the form body.

So putting it all together:

<%= form_for @store do |f| %>
  <%= f.fields_for :products do |product_form| %>
    <%= product_form.select :product, %w[Textbook Magazine Book] %>
  <% end %>
  <%= f.submit %>
<% end %>

2 Comments

I should have been more clear. type_of is actually a field in my product model. I'll change my question to reflect that, sorry.
This is a better approach, but it should be <%= product_form.select :type_of, %w[Textbook Magazine Book] %>. Then I think you have a winner!

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.