Topic: update_attributes method

three tables represent a customer:

1. customer
2. billing_address
3. shipping_address

Sometimes it would be convenient to "pour" the attributes from the billing_address into the shipping_address...

bill = fred.billing_address
=> #<BillingAddress:0x2254f74 @attributes={"city"=>"Bedrock", "zip"=>"88888", "country"=>"USA", "id"=>"5", "customer_id"=>"5", "phone"=>"333 222 2222", "billing_type"=>nil, "address"=>"111 Stone Way", "state"=>"UT"}>

into...

>> ship = fred.shipping_address
=> #<ShippingAddress:0x22432d8 @attributes={"city"=>"", "company"=>"", "zip"=>"", "country"=>"", "id"=>"5", "customer_id"=>"5", "ship_type"=>nil, "phone"=>nil, "first_name"=>"", "address"=>"", "last_name"=>"", "state"=>""}>

I can do this...

>> ship.update_attribute("city", bill.city)
=> true
>> ship.save
=> true

but not this....
>> ship.update_attributes(bill)
NoMethodError: undefined method `stringify_keys!' for #<BillingAddress:0x22074cc>

Could you tell me what is missing from the syntax?

Re: update_attributes method

You can try:

ship.update_attributes(bill.attributes)

However, I recommend merging the two tables. You can have just one addresses table but link to two addresses (billing and shipping) in some other model (such as an order).

class Order < ActiveRecord::Base
  belongs_to :billing_address, :class_name => 'Address', :foreign_key => 'billing_address_id'
  belongs_to :shipping_address, :class_name => 'Address', :foreign_key => 'shipping_address_id'
end

Railscasts - Free Ruby on Rails Screencasts

Re: update_attributes method

so then the relationships look like a tree....

1. customer - has_many orders
2. order - belongs_to_customer
3. addresses(ship and bill) - belong to order

Ryan, how do you see the advantage over? :

1. customer -
has_many :orders
has_one :billing_address
has_one :shipping_address

2. billing_addresses -
  belongs_to :customer

3. shipping_addresses -
  belongs_to :customer

4. order -
has_many :line_items
  belongs_to :customer

Re: update_attributes method

I imagine the shipping_address and billing_address tables have the same columns? They will most likely have the same behavior which is telling me they should be in the same table and model. This is how I have done it (simplified slightly).

Customer
has_many :addresses
has_many :orders

Address
belongs_to :customer

Order
belongs_to :customer
belongs_to :billing_address #...
belongs_to :shipping_address #...


This way a customer has his own set of addresses, he can use the same address for shipping/billing if he wants, or specify two different addresses. He can also have many addresses. I suppose this depends upon how you want the user interface to behave as well.

Railscasts - Free Ruby on Rails Screencasts

Re: update_attributes method

cool!
is the foreign_key relationship any different from a named 'billing_address_id' field in address? So the row in table - 'addresses' and it gets its identity simply from the 'billing_address_id'

And calling it would be either:

customer.address.billing_address 

or

order.billing_address or order.shipping_address?


class Order < ActiveRecord::Base
  belongs_to :billing_address, :class_name => 'Address', :foreign_key => 'billing_address_id'
  belongs_to :shipping_address, :class_name => 'Address', :foreign_key => 'shipping_address_id'
end

Re: update_attributes method

chasC wrote:

cool!
is the foreign_key relationship any different from a named 'billing_address_id' field in address? So the row in table - 'addresses' and it gets its identity simply from the 'billing_address_id'

The billing_address_id column would go in the orders table. Same with the shipping.



chasC wrote:

customer.address.billing_address

You can't reference it in this way because the billing address is dependent upon the order. You can look at a previous order and get the address associated with that:

customer.orders.first.billing_address

I haven't had need to reference it in this way before though.

Railscasts - Free Ruby on Rails Screencasts