Forum: Ruby on Rails nested attributes with update_attributes()

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Bohm (Guest)
on 2005-11-30 15:28
(Received via mailing list)
Hi,
I am trying to use the update_attributes on object with nested
attributes and I am getting the following error:

ProductPrice expected, got HashWithIndifferentAccess

Here's the situation (simplified):

class Product < ActiveRecord::Base
    belongs_to :productPrice
end

class ProductPrice < ActiveRecord::Base
    has_one :product,
                   :dependent => true

    validates_presence_of :costprice, :listprice

end

my parameters look something like this:
        params = {
            :product => {
                :productno => "something",
                :description => "something else",
                :productPrice => {
                    :costprice => 30.34,
                    :listprice => 4.45
                }
            }
        }

I get the error when I run product.update_attributes(params[:product])

Can anybody give me a hint on how to work with nested attributes?

Thanks

Peter
mrj (Guest)
on 2005-11-30 20:04
(Received via mailing list)
Peter B. wrote:

>
>             :product => {
>                 :productno => "something",
>                 :description => "something else",
>                 :productPrice => {
>                     :costprice => 30.34,
>                     :listprice => 4.45
>                 }
>             }
>         }

This'd probably work:

     params[:product][:productPrice] = ProductPrice.new(
params[:product][:productPrice] )
     product.update_attributes( params[:product] )

or

     product.build_product_price( params[:product][:productPrice] )
     params[:product].delete( :productPrice )
     product.update_attributes( params[:product] )

Though:

1. You should use underscore format for your belongs_to (belongs_to
:product_price)
2. If you nest the names in your form the form helpers aren't going to
auto
    fill form values unless you use the form helper compound objects
patch.

    So it'd probably be nicer not to nest the parameters and do:

         product.build_product_price( params[:product_price] )
	product.update_attributes( params[:product] )

--
We develop, watch us RoR, in numbers too big to ignore.
drnicwilliams (Guest)
on 2005-11-30 21:21
(Received via mailing list)
I assume that you have the correct database schema to match the
attributes?

Also, but I don't know if there is any difference, try:
product.attributes =
params[:product]

If the latter fails, can you reply with your DB schema/sql statements?

Cheers
Nic
Bohm (Guest)
on 2005-12-01 03:50
(Received via mailing list)
Hi Mark,
thank you very much for answer
the camel case was just the typo - anyway, thanks for pointing out

As for the rest...
how I've been doing it is very similiar to what you suggested:

product.product_price.update_attributes(params[:product_price])
product.update_attributes(params[:product])

I don't use build_product_price because I am not able to use it with
single table inheritance - e.g. ProductPrice is a "base class" and it's
extended by NetPrice, MarkupPrice, MarkdownPrice, etc. How do I pass the
actual implementation (class type) to the build_xxx method?

Anyways, why I brought the whole thing up is because it's kind of
awkward to have another instance variable for nesting. There is a hint
of this in the agile book (table on p. 343) where the last row uses
user[address][city]=Wien for form parameters. That is translated to
{:user => {:address => {:city ="Wien"}}} and then used as
user.update_attributes(params[:user]).
However, I was neither able to get the form helpers to produce the
nested field nor use the update_attributes :-)

Thanks for help

Peter
Bohm (Guest)
on 2005-12-01 04:02
(Received via mailing list)
Hi Nic,
thanks for reply

product.attributes produces the same error message

please see my other post for more explanation

Do you have something similiar working? I would be very grateful for any
hint how to make it work without workarounds

Here's my schema...it's simplified because in actual situation it uses
inheritance on products, and product prices

create table products (
    id int4 DEFAULT nextval('"products_id_seq"'::text) not null,
    productNo varchar(250) not null,
    description varchar(250) not null,
    product_price_id int4 not null,
    remark text,
    brand_id int4,
    model_id int4,
    contact_id int4,
    created_at timestamp not null,
    updated_at timestamp not null,
    primary key (id)
);
create table product_prices (
    id int4 DEFAULT nextval('"product_prices_id_seq"'::text) not null,
    costPrice numeric not null,
    listPrice numeric not null,
    primary key (id)
);
alter table products
    add constraint fk_product_product_price
    foreign key (price_id)
    references product_prices;

Thank you very much

Peter
mrj (Guest)
on 2005-12-01 04:38
(Received via mailing list)
Peter B. wrote:

> product.product_price.update_attributes(params[:product_price])
> product.update_attributes(params[:product])

I didn't know there was an update_attributes method for belongs_to
associations.  Does this code work?

> I don't use build_product_price because I am not able to use it with
> single table inheritance - e.g. ProductPrice is a "base class" and it's
> extended by NetPrice, MarkupPrice, MarkdownPrice, etc. How do I pass the
> actual implementation (class type) to the build_xxx method?

You should be able to use build_net_price, build_markup_price, and
build_markdown_price.

> Anyways, why I brought the whole thing up is because it's kind of
> awkward to have another instance variable for nesting. There is a hint
> of this in the agile book (table on p. 343) where the last row uses
> user[address][city]=Wien for form parameters. That is translated to
> {:user => {:address => {:city ="Wien"}}} and then used as
> user.update_attributes(params[:user]).
> However, I was neither able to get the form helpers to produce the
> nested field nor use the update_attributes :-)

Yes, p.343 does imply that update_attributes works for nested
parameters.  Though it'd probably work if address was an
aggregration, it won't work for associations.  Perhaps you should
submit an erratum at http://books.pragprog.com/titles/rails/errata .

Nested parameters also don't work with form helpers unless you
use a patch I've placed on the dev site.  Even then, the
update_attributes and new methods won't work unless you fiddle
with the params to properly build the object chain.

--
We develop, watch us RoR, in numbers too big to ignore.
Bohm (Guest)
on 2005-12-01 05:34
(Received via mailing list)
Hi Mark,
the code really works - I guess the first statement will create and save
product_price object (which doesn't have any database reference on
Product) and the second will just create product and associate it with
ProductPrice...

build_net_price, etc. doesn't work - I get NoMethodError

Thank you very much for the rest of the explanation on the nested
associations...I spent a few days on it not being able to work it out
:-(
But isn't it something very common and natural to use associations in
object oriented design?


Peter
mrj (Guest)
on 2005-12-03 15:35
(Received via mailing list)
Peter B. wrote:

>>>product.product_price.update_attributes(params[:product_price])
>>>product.update_attributes(params[:product])
>>
>>I didn't know there was an update_attributes method for belongs_to
>>associations.  Does this code work?

 > the code really works - I guess the first statement will create and
save
 > product_price object (which doesn't have any database reference on
 > Product) and the second will just create product and associate it
with
 > ProductPrice...

Yes, I see now that product_price is just an AR object for which
update_attributes works in its normal way.  Associations just have
some extra or overridden methods besides the normal ones. Useful to
keep in mind.


Peter B. wrote:
 > build_net_price, etc. doesn't work - I get NoMethodError

OK, I thought you had definitions "belongs_to :net_price", etc.

--
We develop, watch us RoR, in numbers too big to ignore.
Bohm (Guest)
on 2005-12-03 20:51
(Received via mailing list)
Hi Mark,
Of course the point is to have a reference to ProductPrice and choose
the implementation at runtime

Thanks for the link to your patch as well

Peter
This topic is locked and can not be replied to.