Reputation: 119
I have a database that keeps track of accidents. Each accident can have multiple causes. Each cause has a friendly name in a 3rd table. What's the 'rails way' to create this association?
Here's what I have:
create_table "accidents", force: true do |t|
t.text "notes"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "causes", force: true do |t|
t.integer "accident_id"
t.integer "cause_name_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "cause_names", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
CauseName.create :name => "DUI"
CauseName.create :name => "Speeding"
Accident:
class Accident ActiveRecord::Base
has_many :causes
end
Causes:
class Cause < ActiveRecord::Base
belongs_to :accidents
has_one :cause_name
end
cause names:
class CauseName < ActiveRecord::Base
belongs_to :causes
end
It seems like to be properly "ORM"'d, I'd use it like this:
Accident.causes.first.cause_name.name #speeding
a = CauseName.find(1)
Accident.causes.first.cause_name = a #set and saved successfully
I've been trying a variety of things, but I can't seem to get my associations to work the way I'd expect. I know I'm not using it right.
I'm very new to rails and activerecord, and horrible with databases... the schema I'm working with was designed by our dba who will be doing reporting on the table, but knows nothing about Ruby or ActiveRecord.
What's the best approach in my situation? Am I even using this thing right?
Upvotes: 0
Views: 48
Reputation: 5367
I think you have your belongs_to
and has_one
methods placed incorrectly in your Cause - CauseName
association.
Quoting the official guide:
If you want to set up a one-to-one relationship between two models, you'll need to add belongs_to to one, and has_one to the other. How do you know which is which?
The distinction is in where you place the foreign key (it goes on the table for the class declaring the belongs_to association), but you should give some thought to the actual meaning of the data as well. The has_one relationship says that one of something is yours - that is, that something points back to you.
So, in your case, it should be like this:
class CauseName < ActiveRecord::Base
has_one :cause # Note that I have changed :causes to singular too
end
class Cause < ActiveRecord::Base
belongs_to :accident # <- Singularized too
belongs_to :cause_name
end
Upvotes: 1
Reputation: 2274
In your case, I'd suggest not splitting causes into two tables. Just cram name
into causes table and call it a day.
Then you can easily query like @accident.causes.first.name
Upvotes: 1