Reputation: 270
I'm working on a Rails app. I encountred a problem with Rails associations: I got 3 models: User, Company and CompanyMember
# id :integer not null, primary key
class User < ActiveRecord::Base
has_one :company_member
has_one :company, through: :company_member
end
# id :integer not null, primary key
# name :string(255) not null
class Company < ActiveRecord::Base
has_many :company_members
has_many :members, through: :company_members, foreign_key: "user_id", source: :user
has_many :admins, -> {where admin: true }, through: :company_members, foreign_key: "user_id", source: :user
end
# id :integer not null, primary key
# company_id :integer
# user_id :integer
# admin :boolean
# created_at :datetime
# updated_at :datetime
class CompanyMember < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
An user can have only one company. He can be admin of this company. A Company can have more than one admin.
so when i want to add a member to the company i do : company.members << user. it's working: when i query company.members it returns the user and the the company_member record is like {user_id: 5, company_id: 8, admin: false}
Now i want to add an user as admin: what i have to do would be this: company.admins << user then company.members should return the user same as company.admins and the company_member record should be like {user_id: 5, company_id: 8, admin: true}
It is possible through Rails associations ? Because actually, it's not working :/ : the company_member is recorded as {user_id: 5, company_id: 8, admin: false} Can you help me ?
Thanks !
I'm using Rails 4.1.3 and ruby 2.1.2
Upvotes: 4
Views: 585
Reputation: 270
I thought what if anyone is interested:
In Company, the association admins must be like this:
class Company < ActiveRecord::Base
has_many :company_members
has_many :members, through: :company_members, source: :user
has_many :admins, -> {where(company_members: {admin: true })}, through: :company_members, source: :user
end
Now I have the expected behavior when i do
company.admins << user
It adds instanciate a company_member with admin: true (which defaults to false)
so I don't need the suggested callback from SampritiPanda but thanks dude !
Upvotes: 0
Reputation: 4465
When you specify a scope in a has_many
relationship, you only customize the query used by has_many. So if you add a User to the list of admins for a company, it does not make it an admin.
You can achieve this by setting a association callback. Rails passes the object being added or removed to the callback, which you can set as the admin.
class Company < ActiveRecord::Base
has_many :company_members
has_many :members, through: :company_members, foreign_key: "user_id", source: :user
has_many :admins, -> {where admin: true }, through: :company_members, foreign_key: "user_id", source: :user, after_add: :set_user_as_admin
def set_user_as_admin(user)
user.company_member.update(admin: true)
end
end
Upvotes: 1