Topic: creating an array from database rows

I am working through the 'Agile Web Development with Rails' book and one of the excercises at the end of the chapter is to replace the drop down list that is hard coded in the chapter as an array with values from a database...

From the chapter we created an array:
PAYMENT_TYPES = [
    # Displayed           stored in db
    [ "Check",            "check" ],
    [ "Credit Card",      "cc"    ],
    [ "Purchase Order",  "po"    ] 
  ]


I have created a new table in the database called payment_types with fields 'display' and 'value' (and of course 'id'). I can't figure out how to get these values into an array like above... I am assuming that is what I need to do...

Can anyone point me in the right direction?

Re: creating an array from database rows

Almost there, but instead of placing the values in an array, use the collection_select method to generate the select menu.

<%= collection_select :model, :attribute, PaymentType.find(:all), :value, :display %>

Replace the :model and :attribute symbols with the proper ones (the same ones you used in the "select" method before.

This assumes there is a PaymentType model, so create that if you haven't already.

You should probably go one step further and set up a relationship for this model. What's the table that stores this payment type? Is it orders? Replace the payment column in the orders table with a "payment_type_id" integer column. You can then set up the associations.

class Order < ActiveRecord::Base
  belongs_to :payment_type
end

class PaymentType < ActiveRecord::Base
  has_many :orders
end


There we go, now you would use the payment_type_id attribute in the collection select.

<%= collection_select :order, :payment_type_id, PaymentType.find(:all), :id, :display %>

Once you get to this point you are using the id of the table to reference the payment type, so you no longer need the "value" column of the payment_types table.

Railscasts - Free Ruby on Rails Screencasts

Re: creating an array from database rows

Thanks!

That makes complete sense...
I had the PaymentType model but had no clue how to use it or link it to the others...

Re: creating an array from database rows

Ok, I have it almost working but I am running into a wierd problem... I can't get the 'display' column to show - the 'id' are placed in the value of the select field but nothing is shown in the display area...

I am using form_for so I have modified things as follows

class PaymentType < ActiveRecord::Base
 
  has_many :orders
 
  def self.get_options
    @payments = find(:all, :order => 'display')
    @options = @payments.collect { |p| [ p.display, p.id ] }
    @options
  end
 
end


class Order < ActiveRecord::Base
 
  validates_presence_of :name, :address, :email, :pay_type_id
 
  has_many :line_items
  belongs_to :payment_type
 
  def add_line_items_from_cart(cart)
    cart.items.each do |item|
      li = LineItem.from_cart_item(item)
      line_items << li
    end
  end
 
end

And in the form
<p>
   <label for="order_pay_type">Pay with:</label>
   <%=
      form.select :pay_type_id,
                  PaymentType.get_options,
                  :prompt => "Select A Payment Method"
   %>
</p>


So why aren't the display values showing?
From the html you can see that the find command is sorting them by the display value:

  <p>
     <label for="order_pay_type">Pay with:</label>
     <select id="order_pay_type_id" name="order[pay_type_id]">
          <option value="">Select A Payment Method</option>
          <option value="2"></option> 
          <option value="1"></option>
          <option value="3"></option>
     </select>
  </p>

value 2 should show "Check", value 1 should show "Credit Card", and value 3 should show "Purchase Order"

Re: creating an array from database rows

Try running script/console and see if display is returning the proper result. I'm thinking "display" may be a reserved word, so it my not be working properly.

# in script/console
type = PaymentType.find(:first)
type.display

Also, pay_type_id should be payment_type_id so Rails can do its column-name magic and reference the association automatically. This wouldn't be causing the problem you have now though.

Railscasts - Free Ruby on Rails Screencasts

Re: creating an array from database rows

Apparently display is a reserved word or method. I changed display to payment in the db and everywhere else as well as making the chage from pay_type_id to payment_type_id and everything works!

Thanks a bundle for the help!

Re: creating an array from database rows

No problem. You still may want to use collection_select.

<%= form.collection_select :payment_type_id, PaymentType.find(:all, :order => 'payment'), :id, :payment %>

This way you don't need the get_options method. You still may want to move the find into a method though, so it's not in the view.

Railscasts - Free Ruby on Rails Screencasts