Misha Moroshko
Misha Moroshko

Reputation: 171321

Ruby on Rails: Why a select box does not show the current object value?

Here is the relevant code from views/products/edit.html.erb:

<%= form_for(:product, :url => {:action => 'update', :id => @product.id}) do |f| %>
  <%= render(:partial => "form", :locals => {:f => f}) %>
  <%= submit_tag("Update Product") %>
<% end %>

from views/products/_form.html.erb:

<%= select_with_new_option(f, :shop, :name, :id) %>

and from helpers/products_helper.rb:

def select_options_with_create_new(objects, text_field, value_field, options={})
  object = objects.to_s.singularize
  all_objects = object.capitalize.constantize.all
  all_objects = all_objects.sort_by(&options[:order_by]) if options.has_key?(:order_by)
  select_options = all_objects.map{ |obj| [obj.send(text_field), obj.send(value_field)] }
  select_options << [wrap_create_new_option("create new #{object}".titleize), "new_#{object}"]
  options_for_select(select_options)
end

def wrap_create_new_option(str)
  ">> #{str} <<"
end

# By default, sorts by 'text_field'.
def select_with_new_option(f, object, text_field, value_field)
  f.select(:"#{object}_id", select_options_with_create_new(object.pluralize, text_field, value_field, :order_by => text_field))
end

I expect the select box to be @product.shop_id by default, but this is not true (the first option is always the default value).

What am I missing ?

Upvotes: 3

Views: 2747

Answers (2)

Kevin
Kevin

Reputation: 1855

Alright, I got it. Just remove options_for_select(select_options) in the select_options_with_create_new method.

The options_for_select assembles the 2-d array select_options into a string of html options, which is accepted by the select form helper, however, without assigning the selected attribute. Just pass the 2-d array to the select method as the second argument, it would assign the selected automatically.

Upvotes: 7

Sam Ritchie
Sam Ritchie

Reputation: 11038

I think that, in this case, all you need to do is make sure you set @product in your edit action:

def edit
  @product = Product.find(params[:id])
end

Then change your first line:

<%= form_for(:product, :url => {:action => 'update', :id => @product.id}) do |f| %>

to

<%= form_for(@product, :url => {:action => 'update', :id => @product.id}) do |f| %>

The first code block will certainly update the proper product, but you'll only see the current values reflected if you generate a form_for @product, with that @product variable set.

Upvotes: 0

Related Questions