rmaspero
rmaspero

Reputation: 633

Belongs To Foreign Key

I am getting massively stuck on an belongs_to relationship that should be pretty simple in my mind.

If I create a database association in a migration from a Ticket to an Account, it makes a database field called 'account_id' on the Tickets table, which is fine. Then in my Ticket model I put:

belongs_to :created_by, class_name: 'Account'

But as of rails 5, belongs_to relationships automatically add a validation of presence of requirement for account_id. But if I pass in a created_by it fails the validation. As I want to validate presence of created_by not account_id. So I add the optional: true tag

belongs_to :created_by, class_name: 'Account', optional: true

then validate presence of created by separately

validates_presence_of :created_by

this all works, but I don't like that I contradict myself by saying optional and then validate it a line later for what is really the same field!

I then got to thinking what if the field in the database on the tickets table is actually called created_by and using some primary and foreign key stuff I build the relationship it should fix it right?

But I am unsure how to build the migration and then how on earth to write the belongs_to. I had tried:

add_column :tickets, :created_by, :bigint
add_index :tickets, :created_by

and

belongs_to :created_by, class_name: 'Account', foreign_key: :created_by, primary_key: :account_id

but this complete fails, however if I do

belongs_to :account, foreign_key: :created_by

this enables me to update created_by with say an account_id of 1, but if I run ticket.created_by I get the int and ticket.account returns the account. I want this to be the other way around.

Upvotes: 2

Views: 12988

Answers (1)

rmaspero
rmaspero

Reputation: 633

So my issue was in the way the migration interacted with rails relationships. I was creating a column called created_by and storing an id in it. Which meant created_by returned the id not the relationship.

The migration should have looked like:

add_reference(:tickets, :created_by, foreign_key: {to_table: :accounts})

which creates a created_by_id on the tickets table. Then on the tickets model all I needed was:

belongs_to :created_by, class_name: 'Account'

and for an account to see its tickets you would be able to do:

has_many :tickets, foreign_key: 'created_by_id'

Upvotes: 9

Related Questions