Reputation: 805
Updated the question as original was over simplistic, thanks to Aaron McLeod aka AGMCLEOD for your help highlighting this
My problem is such that it is not that I cannot get it to work, but getting it to work how I want.
The problem
Imagine 3 models, a Company, Branch and a Contact, they are linked together through a CompanyContacts model or a look-up table.
The table company_contacts looks like this:
+------------+-----------+------------+
| company_id | branch_id | contact_id |
+------------+-----------+------------+
and my ideal statements for relating a contact to a branch and company should be:
update company_contacts set contact_id = x where branch_id = y AND company_id = z
So the question, How is this possible using ActiveRecord? Do you create custom methods to set it in one go?
What I have in my models
CompanyContact Model
belongs_to :company, :class_name => "Company", :foreign_key => :company_id
belongs_to :branch, :class_name => "Branch", :foreign_key => :branch_id
belongs_to :contact, :class_name => "Contact", :foreign_key => :contact_id
Company Model
has_many :company_contacts
has_many :branches, :through => :company_contacts, :source => :branches
has_many :contacts, :through => :company_contacts, :source => :contacts
Branch Model
has_many :company_contacts
has_many :companies, :through => :company_contacts, :source => :companies
has_many :contacts, :through => :company_contacts, :source => :contacts
I would love to be able to do the following but it is not possible
has_one :company, :through => :company_contacts, :source => :company
Of course I could simulate it by
def branch
Branch.companies.first
end
Contact Model
has_many :company_contacts
has_many :branches, :through => :company_contacts, :source => :branches
has_many :companies, :through => :company_contacts, :source => :companies
Again ideally i would like to have, has_one branch and has_one company
My current solution when creating a contact and << to a branch results in two rows being created
+------------+-----------+------------+
| company_id | branch_id | contact_id |
+------------+-----------+------------+
| 1 | 1 | nil |
+------------+-----------+------------+
| nil | 1 | 1 |
+------------+-----------+------------+
When, what in fact I would like to achieve is:
+------------+-----------+------------+
| company_id | branch_id | contact_id |
+------------+-----------+------------+
| 1 | 1 | 1 |
+------------+-----------+------------+
The only way I can think of doing this is creating a custom method
I will continue to try and resolve my issue and post my findings Look forward to your replies
Thanks in advance.
Upvotes: 0
Views: 956
Reputation: 13611
To solve this, you can do something like the following. Assuming you're passing the branch id and company id through the form, or if you have it already in the url.
def create
@contact = Contact.new(params[:contact])
if @contact.save
cc = CompanyContact.new(:contact_id => @contact.id, :branch_id => params[:branch_id], :company_id => params[:company_id])
cc.save
redirect_to contacts_url, :notice => "Contact saved"
else
render :action => "new"
end
end
You might need to adjust parameter names and such, but that should work. Because it is a bit of three way connection, I'm not sure if there's a way to build it right on the contact object.
Upvotes: 0
Reputation: 805
ok after a hell of a lot more digging around after posting the question I came across this awesome answer to something similar. zetetic provided a very detailed answer and I read up in a little more depth on how to resolve this issue.
First the inspiration: has_many :through multiple has_one relationships?
Now the answer:
In the create method in your ContactController the magic 1 line of code is:
@contact.company_contacts.build(:company_id => @company.id, :branch_id => @branch.id)
So in full in ContactController's create method:
# fetch the branch and company ids first
@contact = Contact.new(params[:contact])
@contact.company_contacts.build(:company_id => @company.id, :branch_id => @branch.id)
@contact.save
and it does exactly what I wanted to achieve with:
INSERT INTO "company_contacts" ("branch_id", "company_id", "contact_id") VALUES (?, ?, ?) [["branch_id", 2], ["company_id", 4], ["contact_id", 12]]
Phew - took me a while for some reason and seems so simple looking at it!
Upvotes: 1