Hi Leandro,
You can reach the materials through the compositions, and you should worry
about doing extra queries in the DB since you have used the includes
method. You should iterate through them to get the list of material names.
Say we have:
@compositions = @p.compositions.include(:materials)
@material_names = @compositions.map { |c| c.materials.map(&:name) }
@material_names will return you an array of arrays with the material names.
Since you have the has many through setup, you can call
@product.materials.map(&:name) directly and you will get a flattened array
with the materials' names.
Best regards,
Marco
On Mon, Mar 30, 2015 at 4:33 PM, Leandro França <
[email protected]> wrote:
>
> Hey Marco,
>
> Thanks a lot for you quick response.
>
> So, I tried to change my models to use only *has_many* and *belongs_to*,
> instead of *has_and_belongs_to_many*.
> I also added the foreign key to material_id:
>
>
>
> class Composition < ActiveRecord::Base
> belongs_to :material, :class_name => "Material", :foreign_key =>
> 'material_id'
> belongs_to :product
> end
>
>
> class Material < ActiveRecord::Base
> has_many :compositions
> has_many :products, through: :composition
> end
>
> class Product < ActiveRecord::Base
> has_many :compositions
> has_many :materials, through: :composition
> end
>
> On rails console, I can run fine:
>
> @p = Product.first
> @p.compositions
> @p.compositions.includes(:material)
>
> But this last one returns me only the items I already have on composition,
> not the actual material attributes.
>
>
> @p.compositions.includes(:material)
> Composition Load (0.5ms) SELECT "compositions".* FROM "compositions"
> WHERE "compositions"."product_id" = $1 [["product_id", 1]]
> Material Load (0.7ms) SELECT "materials".* FROM "materials" WHERE
> "materials"."id" IN (1, 2)
> => #<ActiveRecord::AssociationRelation [#<Composition id: 5, product_id:
> 1, material_id: 1, material_quantity: 3, created_at: "2015-03-30 05:20:27",
> updated_at: "2015-03-30 05:20:27">, #<Composition id: 6, product_id: 1,
> material_id: 2, material_quantity: 2, created_at: "2015-03-30 05:20:27",
> updated_at: "2015-03-30 05:20:27">]>
>
> I would like to also get the material names from Material model.
> How do I get them using this approach?
>
> Thanks again,
> Leandro
>
>
> On Monday, March 30, 2015 at 10:58:52 AM UTC-3, Marco Antonio wrote:
>>
>> Now I see that you have the quantity inside your compositions table and
>> you probably need that.
>>
>> You can use the code you have in your controller normally with the
>> changes mentioned in my last e-mail.
>>
>> *Marco Almeida*
>> about.me/marcoafilho
>> +45 31 65 28 84
>>
>> On Mon, Mar 30, 2015 at 3:53 PM, Marco Antonio Almeida <
>> [email protected]> wrote:
>>
>>> Hi Leandro,
>>>
>>> The way it is set up right now, you would actually have in the
>>> Composition model a belongs_to :material. And the Material would have a
>>> has_many :compositions.
>>>
>>> Verify that you have the foreign key set in your Composition model, so
>>> you would never be able to do something like: composition.materials.
>>>
>>> Since you have the has_many through association you could simply call.
>>> @product.materials and it will return what you want (It will do the INNER
>>> JOIN through the compositions table).
>>>
>>> The error you're getting is because when you're using a has_and_belongs
>>> to many, Rails expect to have a relationship table named after the two
>>> models in the plural. But in this case your compositions table is already
>>> the relationship table.
>>>
>>> Best regards,
>>> Marco Almeida
>>>
>>> On Mon, Mar 30, 2015 at 3:20 PM, Leandro França <[email protected]>
>>> wrote:
>>>
>>>> Hi there,
>>>>
>>>> I'm learning the active model, and I'm trying to retrieve an
>>>> association.
>>>>
>>>> My models are:
>>>>
>>>> class Composition < ActiveRecord::Base
>>>> has_and_belongs_to_many :materials
>>>> belongs_to :product
>>>> end
>>>>
>>>> class Material < ActiveRecord::Base
>>>> has_and_belongs_to_many :compositions
>>>> has_many :products, through: :composition
>>>> end
>>>>
>>>> class Product < ActiveRecord::Base
>>>> has_many :compositions
>>>> has_many :materials, through: :composition
>>>> accepts_nested_attributes_for :materials
>>>> end
>>>>
>>>>
>>>> My schema is:
>>>>
>>>>
>>>> create_table "compositions", force: :cascade do |t|
>>>> t.integer "product_id"
>>>> t.integer "material_id"
>>>> t.integer "material_quantity"
>>>> t.datetime "created_at", null: false
>>>> t.datetime "updated_at", null: false
>>>> end
>>>>
>>>>
>>>> create_table "materials", force: :cascade do |t|
>>>> t.string "name"
>>>> t.decimal "unit_cost"
>>>> t.string "unit_measure"
>>>> t.datetime "created_at", null: false
>>>> t.datetime "updated_at", null: false
>>>> end
>>>>
>>>>
>>>> create_table "products", force: :cascade do |t|
>>>> t.string "name"
>>>> t.string "description"
>>>> t.datetime "created_at", null: false
>>>> t.datetime "updated_at", null: false
>>>> end
>>>>
>>>> On my CompositionsController index method, I would like to retrieve all
>>>> raw materials for a product id.
>>>>
>>>> What i have now is:
>>>>
>>>> def index
>>>> @product = Product.find(params[:product_id])
>>>> @compositions = @product.compositions
>>>> end
>>>>
>>>>
>>>> How do I retrieve materials attributes from @compositions?
>>>>
>>>> When I try to use
>>>> @compositions = @product.compositions.includes(:materials)
>>>> It gives me the error:
>>>>
>>>> PG::UndefinedTable: ERROR: relation "compositions_materials" does not
>>>> exist
>>>> LINE 5: WHERE a.attrelid = '"compositions_materials"'...
>>>> ^
>>>> : SELECT a.attname, format_type(a.atttypid, a.atttypmod),
>>>> pg_get_expr(d.adbin, d.adrelid), a.attnotnull,
>>>> a.atttypid, a.atttypmod
>>>> FROM pg_attribute a LEFT JOIN pg_attrdef d
>>>> ON a.attrelid = d.adrelid AND a.attnum = d.adnum
>>>> WHERE a.attrelid = '"compositions_materials"'::regclass
>>>> AND a.attnum > 0 AND NOT a.attisdropped
>>>> ORDER BY a.attnum
>>>>
>>>>
>>>>
>>>> Any hints?
>>>>
>>>> Thanks in advance,
>>>> Leandro
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Ruby on Rails: Talk" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>> To post to this group, send email to [email protected].
>>>> To view this discussion on the web visit https://groups.google.com/d/
>>>> msgid/rubyonrails-talk/643eb535-3085-46d4-b77b-
>>>> 5c50c6cb7636%40googlegroups.com
>>>> <https://groups.google.com/d/msgid/rubyonrails-talk/643eb535-3085-46d4-b77b-5c50c6cb7636%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/rubyonrails-talk/be51416c-4340-4c12-afff-702f67820f0f%40googlegroups.com
> <https://groups.google.com/d/msgid/rubyonrails-talk/be51416c-4340-4c12-afff-702f67820f0f%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google Groups "Ruby
on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/rubyonrails-talk/CACMkcE6ADW%3DsoCxXfyti-q5Z1H5RWJ54CNfnH_2V89Y0R1t%2Bdw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.