Ryan C.
Ryan C.

Reputation: 119

has_many or join - what's the 'rails way' to use my table?

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

Answers (2)

mpj
mpj

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

Grocery
Grocery

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

Related Questions