0

I am trying to get the right association for my models and can't figure it out.

I have 3 models, Bat, Manufacturer, & Review. Here are my models:

class Bat < ActiveRecord::Base
  has_many :reviews
  has_one :manufacturer
end

class Manufacturer < ActiveRecord::Base
  has_many :bats
end

class Review < ActiveRecord::Base
  belongs_to :bat
end

In the Review model, it has a bat_id & manufacturer_id field. In the Bat model, it has a manufacturer_id field.

I am trying to properly link the manufacturer model to the bat model.I have looked at http://guides.rubyonrails.org/association_basics.html#self-joins and I am not sure that is the type of relationship that I need.

Is this correct or am I missing something?

Daniel
  • 2,950
  • 2
  • 25
  • 45

3 Answers3

1

As you can see by the self-join docs, self joining is used to join a model to itself. You don't need to do this, because a manufacturer does not belong to another manufacturer in any way (at least, not from what I can tell from your description).

Also, your Review model does not need to be linked to the Manufacturer model (aka, you do not need manufacturer_id on the Review model.

Your bat model should have belongs_to :manufacturer, because it belongs to the manufacturer, it doesn't have one. You can read more about belongs_to vs has_one here: http://guides.rubyonrails.org/association_basics.html#choosing-between-belongs-to-and-has-one

All you need is a manufacturer_id on your Bat table, and a bat_id on your Review table. Then you'll be able to use all the Rails magic, like

bat.manufacturer # get the manufacturer of a bat
manufacturer.bats # get all the bats from a manufacturer
bat.reviews # get all the reviews for a bat

Obviously you will need to create the migrations to add the fields to the database, eg

rails generate migration add_manufacturer_id_to_bat manufacturer_id:integer
rails generate migration add_bat_id_to_review bat_id:integer
rake db:migrate
Christian
  • 19,605
  • 3
  • 54
  • 70
  • Okay thanks it makes sense. I am using manufacturer_id in my review table because it allows me to set up a form with two drop down selections. In one dropdown the user selects the manufacturer and in the other they select the bat name. I would like to use javascript (working on that based on http://www.chasepursley.com/dynamic-select-slash-dropdown-menus-with-rails-3-plus-on-the-client-side) to allow for a good UI. It would be nice to only store the bat_id in the review table based on dynamic drop downs but I can't figure that out. (thats why I have bat_id & manufacturer_id) – Daniel Feb 16 '14 at 02:55
  • I have been trying to figure out how to solve that problem here http://stackoverflow.com/questions/21690556/rails-multiple-input-field-in-form-to-one-integer-attribute-in-model – Daniel Feb 16 '14 at 02:56
  • I can't get `bat.manufacturer` to work, only `bat.manufacturer_id` will show the integer. – Daniel Feb 16 '14 at 03:01
  • Are you sure that your associations are correct? Eg, `belongs_to :manufacturer` in Bat model and `has_many :bats` in Manufacturer model? – Christian Feb 16 '14 at 03:11
  • @ravensfan55222 Unfortunately I just don't have enough information to tell you what the problem is, because Rails associations do work, and all they need to work is a field in a database and the correct association to be set in the model. Normally I don't do this, but I've set up a demo app for you which demonstrates the use of associations. You can view it here on Heroku: http://secret-bayou-5954.herokuapp.com/, you'll notice the Manufacturer name next to the bats. View the source here: https://github.com/levymetal/stackoverflow-bats. Compare this to yours, and see where the difference lies. – Christian Feb 16 '14 at 08:05
  • thank you, I figured out it should be `bat.manufacturer.manufacturer` My column is named manufacturer (which is what I was missing) I want to fork your example because you took the time to provide a good example for me showing the associations. Thank you! – Daniel Feb 16 '14 at 20:26
  • @ravensfan55222 ah yeah, `bat.manufacturer` will return the entire manufacturer object. So as you figured you can access the attributes after that, eg `bat.manufacturer.manufacturer`, `bat.manufacturer.id` etc. Yeah feel free to fork / do whatever you wish with that code! – Christian Feb 17 '14 at 00:43
0

Because your Manufacturer has many bats, your Bat belongs to one Manufacturer, so I think that changing has_one :manufacturer for belongs_to :manufacturer will resolve your problem.

Rafa Paez
  • 4,820
  • 18
  • 35
-1

Change your Bat Class to

class Bat < ActiveRecord::Base
  has_many   :reviews
  belongs_to :manufacturer
end
ahnbizcad
  • 10,491
  • 9
  • 59
  • 85
  • This answer is correct. The op says the bat "has one manufacturer" while the manufacturer "has many bats". every `has_many` or `has_one` requires a `belongs_to` counterpart on the other model. you cannot have two `has_*` on both ends of a model association. – ahnbizcad Sep 23 '14 at 01:05