How to populate a table with id of selected item from another table

Hi,

I have a "New Expense" form that includes a select field named vendor that provides a a drop-down list of all vendors.

When a user makes a selection of a vendor-name, that name populates the vendor field of the new Expense record. I'm happy with the drop- down list of names, but I'd rather populate the Expense record with the ID of the vendor.

IMHO, this is a common database problem. Can you point me to a simple example on the Web for handling this. I've found plenty of HABTM examples with check-boxes, but none (so far) exactly on point.

Thanks in Advance, Richard

OK, so populate the option values with the ID. This is basic HTML.

RichardOnRails wrote:

Hi,

I have a "New Expense" form that includes a select field named vendor that provides a a drop-down list of all vendors.

When a user makes a selection of a vendor-name, that name populates the vendor field of the new Expense record. I'm happy with the drop- down list of names, but I'd rather populate the Expense record with the ID of the vendor.

IMHO, this is a common database problem. Can you point me to a simple example on the Web for handling this. I've found plenty of HABTM examples with check-boxes, but none (so far) exactly on point.

Just use collection_select or something. What exactly are you having trouble with?

Thanks for your responses, Hassan and Marnen.

This is what I had, which returned vendors' names and parenthesized nicknames:

    <% def parens(s); s.empty? ? "" : " (#{s})"; end -%>     <% @current_vendors = Vendor.find(:all, :order=>"nickname").collect { |v|       v.nickname + parens(v.qbname) } %>     <%= f.select :vendor, @current_vendors %>

In response, to Hassan's suggestion, I used the following which (as I expected) presented merely ids and no names which a user could use to identify the desired vendor:

    <% @current_vendors = Vendor.find(:all, :order=>"nickname").collect { |v|       v.id } %>     <%= f.select :vendor, @current_vendors %>

What I want is to have vendor-names to be displayed in the drop-down and the selected name to be displayed in the form but, upon submission, have the selected vendor's ID stored in the database rather than the selected name.

Best wishes, Richard

If you (hint, hint) look at the API doc for `select`, you'll see an example of *exactly* the result you're trying to achieve.

Hassan Schroeder wrote:

Okay, guys: I can take a hint :slight_smile: Finally I did a Google search based on your hit that got me what I was heretofore unable to find: "rails api select"

I don't have time today to code and test this, so I'll just post my ideas here to see if they sound sensible to you guys.

In my "New Expense" form:     <%= f.collection_select(:vendor, :vendor_id, Vendor.all, :id, name_w_nickname -%>

In my Expense class:     belongs_to :vendor

In my Vendor class:     has_many :expenses and     def name_w_nickname         %<%s (%s)> % [name, nickname]     end

I need to do something about possible nil in the nickname field, maybe: nickname ||= "".

If you guys are up to it, I'd appreciate any observations you may care to offer.

Best wishes, Richard

Okay, guys: I can take a hint :slight_smile: Finally I did a Google search based on your hit that got me what I was heretofore unable to find: "rails api select"

Wow. You've been doing Rails development without using the API docs? Kinda like playing tennis in the dark. in handcuffs. :slight_smile:

In my "New Expense" form: <%= f.collection_select(:vendor, :vendor_id, Vendor.all, :id, name_w_nickname -%>

As already mentioned -- don't do DB access in the view. Move that Vendor.all to your controller and use it to set a var, e.g. @vendors.

Aside from theoretical considerations, it means you don't have to change any views when you have a business need to replace the `Vendor.all` with, say, a named scope like `Vendor.approved`.

FWIW,

Hi Hissan,

Thanks for your response.

Wow. You've been doing Rails development without using the API docs? Kinda like playing tennis in the dark. in handcuffs. :slight_smile:

Well, I wasn't completely without resources, e.g. the links (now expanded, thanks to you) I maintain under one Firefox tab: <a href="http://www.ruby-doc.org/core/&quot;&gt;Ruby\-Doc\.org/core&lt;/a&gt;&lt;/p&gt; <a href="http://stdlib.rubyonrails.org/&quot;&gt;Ruby Standard Library Documentation</a></p> <a href="Ruby | zenspider.com | by ryan davis QuickRef.html</a></p> <a href="Active Record Migrations — Ruby on Rails Guides Guide: Migrations</a></p> <a href="http://www.williambharding.com/blog/rails/rails-scriptserver- command-line-options">rails-scriptserver-command-line-options</a></p> <a href="http://guides.rubyonrails.org/command_line.html&quot;&gt;RubyOnRails Guide: command_line</a></p> <a href="http://dizzy.co.uk/ruby_on_rails/cheatsheets/rails- migrations">RubyOnRails Migrations CheatSheet</a></p> <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/ FormOptionsHelper.html">RubyOnRails: FormOptionsHelper</a></p>

and my Rails library: The Rails Way Rails Cookbook Practical Prototype & Script.aculo.us Rails Recipes Advanced Rails Recipes Practical REST on Rails 2 Projects ... and quite a few more

That was the fun part. Here's the serious question:

1. When I bring up my app and click the link for "New Expense", I see "http://localhost:3000/expenses/new&quot; in Firefox' Address bar and I get the following 10 lines or so:

NameError in Expenses#new

Showing app/views/expenses/new.html.erb where line #10 raised:

undefined local variable or method `nickname' for #<ActionView::Base: 0x442c8f0>

Extracted source (around line #10):

7: 8: <p> 9: <%= f.label :vendor %><br /> 10: <%= f.collection_select(:vendor, :vendor_id, @vendors, :id, nickname) -%> 11: <%= link_to 'New Vendor', :controller=>'vendors', :action=>'new' %> 12: </p> 13: <p>

2. I think "nickname" is a legitimate method for Vendor. For example, if I load Firefox' Address bar with "http://localhost:3000/vendors&quot;, I get:

Listing vendors Home Vendor Expense Nickname QB_name 001v One Show Edit Destroy 002v Two Show Edit Destroy 003nick 003qb Show Edit Destroy [snip]

3. I tried a colon in front of "nickname" in the f.collection_select statement to no avail; besides, the documentation you referred to suggested a bareword.

4. Any ideas?

Thanks in Advance, Richard

? I'm looking at (unframed)

<http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#M002303&gt; with this 'sample usage':

  collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})

Are you sure you got the *exact same* error using :nickname ?

If so, what's the code that creates @vendors ?

Hi Hassan,

Thanks for your continued consideration of my problem. I hope some of the following is helpful, though it seems like way to much information.

? I'm looking at (unframed)

<http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelp...&gt; with this 'sample usage':

  collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})

Here’s the section of of the doc I looked at: ActionView::Helpers::FormOptionsHelper, which seems to match the portion you cited.

Are you sure you got the *exact same* error using :nickname ?

Since this section referenced a method that returned a string, I took a short-cut to simply name an object whose value was a string. But in case that’s the cause of the problem, I changed my app to closely follow the example in the doc.

If so, what's the code that creates @vendors ?

Good question: I DON’T KNOW! I see a several methods in app \controllers\vendors_controller.rb the populate @vendors with Vendor.all. Maybe the absence of an assignment to @vendors is what’s wrong, but I don’t know what to do about it/

Carrying on in case the changes I made are useful, I note that this section shows the command format as follows:

collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})

It shows the object structure to be used with this method:   class Post < ActiveRecord::Base     belongs_to :author   end   class Author < ActiveRecord::Base     has_many :posts     def name_with_initial       "#{first_name.first}. #{last_name}"     end   end

I’ve got: app\models\expense.rb:     class Expense < ActiveRecord::Base         belongs_to :vendor     end

and app\models\vendor.rb:     class Vendor < ActiveRecord::Base       has_many :expenses

      def name           #{nickname}     end

I’ve got a *revised* app\views\expenses\new.html.erb, lines 8-12 in order to follow the example more exactly:   <p>     <%= f.label :vendor %><br />     <%= f.collection_select(:vendor, :vendor_id, @vendors, :id, :name) -%>     <%= link_to 'New Vendor', :controller=>'vendors', :action=>'new' %>   </p>

When I run the app and click on the New Expense link, I get a *revised* symptom, which is the error page below starting with **NoMethodError in Expenses#new** in 24-point font.

I can post all the app’s code or any partion thereof in a zip file if that would be helpful to you.

Thank you for helping me to get this functionality going.

Best wishes, Richard

NoMethodError in Expenses#new Showing app/views/expenses/new.html.erb where line #10 raised: undefined method `merge' for :name:Symbol Extracted source (around line #10): 7: 8: <p> 9: <%= f.label :vendor %><br /> 10: <%= f.collection_select(:vendor, :vendor_id, @vendors, :id, :name) -%> 11: <%= link_to 'New Vendor', :controller=>'vendors', :action=>'new' %> 12: </p> 13: <p> RAILS_ROOT: K:/_Projects/Ruby/_Rails_Apps/_EIMS/RTS Application Trace | Framework Trace | Full Trace K:/_Utilities/ruby186-26_rc2/ruby/lib/ruby/gems/1.8/gems/ actionpack-2.3.5/lib/action_view/helpers/form_helper.rb:1025:in `objectify_options' K:/_Utilities/ruby186-26_rc2/ruby/lib/ruby/gems/1.8/gems/ actionpack-2.3.5/lib/action_view/helpers/form_options_helper.rb:588:in `collection_select' K:/_Projects/Ruby/_Rails_Apps/_EIMS/RTS/app/views/expenses/ new.html.erb:10:in `_run_erb_app47views47expenses47new46html46erb' K:/_Projects/Ruby/_Rails_Apps/_EIMS/RTS/app/views/expenses/ new.html.erb:5:in `_run_erb_app47views47expenses47new46html46erb' K:/_Projects/Ruby/_Rails_Apps/_EIMS/RTS/app/controllers/ expenses_controller.rb:30:in `new' Request Parameters: None Show session dump Response Headers: {"Content-Type"=>"text/html", "Cache-Control"=>"no-cache"}

Hassan,

Please hold off on looking at my last, unreasonably large post. I'm embarrassed to have posted such a monstrosity.

I found a bunch of tutorials on collection_select, so I should be able to discover where I've gone astray in trying to apply that method in my app. I'll post back how I solved my problem using those resources, should I be so fortunate.

Best wishes, Richard