I've got a Rails 3.1 app with a User model and a House model (this is like a group). I've set up a many-to-many relation with join model Membership between those two and there are methods to manages roles of a user in some house in the join model.
But my problem is that a User has only one house and not many. So I always have to do user.houses.first to get his house (I've set up a helper house which does that) but the design is not good so I've tried to put has_one :membership and has_one :house, :through => :membership instead of has_many :memberships and has_many :houses, :through => :memberships. But I got an error each time I try to access house from User.
How is it possible to set up this one-to-many relation with a join table like I was trying to do ?
Thank you in advance.
If you are going to use the one to many relation then association should be.
House
has_many :memberships
has_many :users, :through => :memberships
User
has_one :membership
has_one :house, :through => :membership
I can't think of a way doing this with relations, however you could leave it as the plural and then just define house in users:
class User
has_many :memberships
has_many :houses, :through => :memberships
def house
houses.first
end
end
Related
I'm having problems with a Rails 4 join table. I have quite a simple setup which is working elsewhere in my application using a non-conventionally named table for users, groups and usergroupmemberships. I'm trying to set it up this time using the proper conventional naming and it's just not working.
Models involved are User, ManagementGroup and ManagementGroupsUser
db tables: management_groups_user, management_groups, users
app/models/user.rb
Class User < ActiveRecord::Base
...
has_many :management_groups, through: management_groups_users
has_many :management_groups_users
....
app/models/management_group.rb
class ManagementGroup < ActiveRecord::Base
has_many :users, through: :management_groups_users
has_many :management_groups_users
app/models/management_groups_user.rb
class ManagementGroupsUser < ActiveRecord::Base
belongs_to :users
belongs_to :management_groups
The association appears to work from with #user.management_groups_users but nothing else. I'm fairly sure this is a problem with naming / plurality but I can't figure it out.
This is the model which joins the remaining models user.rb and management_group
#app/models/management_groups_user.rb
belongs_to :user
belongs_to :management_group
Since we are going to use model above to access another model management_group then
#app/models/user.rb
has_many :user_management_groups #This should come first
has_many :management_groups, through: user_management_groups
Since we are going to use model above to access another user model then
app/models/management_group.rb
has_many :user_management_groups
has_many :users, through: :user_management_groups
Now should work
Do it this way.
app/models/user.rb
has_many :user_management_groups
has_many :management_groups, through: user_management_groups
app/models/management_group.rb
has_many :user_management_groups
has_many :users, through: :user_management_groups
app/models/management_groups_user.rb
belongs_to :user
belongs_to :management_group
I hope these associations will help you.
This is another way if you pass foreign key and class name.
app/models/user.rb
has_many :user_management_groups, :foreign_key => "key", :class_name => "ClassName"
has_many :management_groups, through: user_management_groups, :foreign_key => "key", :class_name => "ClassName"
app/models/management_group.rb
has_many :user_management_groups
has_many :users, through: :user_management_groups
app/models/management_groups_user.rb
belongs_to :user, class_name: "ClassName"
belongs_to :management_group, class_name: "ClassName"
This is another way around.
It's important to realize there is a convention rails uses for HABTM and has many through. HABTM does not have a model, so it needs to infer the table name which, as others point out, is both plural and alphabetical order.
If you are doing has many through and have a model, the convention is that it wants singular first word, plural second. See examples
User has and belongs to many groups.
HABTM: table name should be groups_users
Has Many Through: table name should be user_groups (flip order is more intuitive)
Model for the latter would be UserGroup. Has many through would specify it as through: :user_groups
I have three models - Company, User and CompanyUser. The associations are as follows.
Company.rb
has_many :company_users
has_many :users, :through => :company_users
User.rb
has_many :company_users, :dependent => :destroy
belongs_to :company
CompanyUser.rb
belongs_to :company
belongs_to :user
For fetching current_user.company, what moddifications are to be made in the model association?
Any help would be appreciated.
It should be:
has_many :companies, through: :company_users
A has_many :through association is often used to set up a many-to-many
connection with another model. This association indicates that the
declaring model can be matched with zero or more instances of another
model by proceeding through a third model.
So if you are creating three models and making a has_many :through association I believe that User will have many Companies and Company will have many Users.
But if you need that the user belongs to only one company instead of creating the third model save the company_id in the users table itself.
Update:
Now as your scenario is A company can have may users and User belongs to a single company, you need two models: User and Company. Your User model should have an attribute company_id and then company_id should be saved in users table only. Then the associations as follows:
class User < ActiveRecord::Base
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :users
end
Then you can do current_user.company
You can get more information on associations in the RailsGuides
According to the associations you have taken,
user already have as association with the company through the Company User model, so user may have many companies according to your associations.
so,
class User < ActiveRecord::Base
has_many :company_users, :dependent => :destroy
has_many :companies, :through => :company_users
end
current_user.companies will give you the companies.
But if you need only one company for a user then,
class User < ActiveRecord::Base
belongs_to :company
end
take belongs_to company and save company_id in users table,
then you can call,
`current_user.company`
According to your logic,
I think you may need to create a new variable session current_company_user which is object CompanyUser.
And then, to fetch company by :
current_company_user.company
My database stores data about a TV show. I want to store information about who worked on what episodes, and in what role.
Each crew member works on many episodes; each episode has many crew members; and crew members can work on the same episode in different roles (they can be writer and director on the same episode, for example).
I'm new to thinking about ActiveRecord, so I'm a bit confused about how to properly represent these relationships in Rails. I would really love it if someone could tip me off as to the 'Rails way' to do this.
My instinct is to create a triple-join (or double-join; three fields, anyway) table. I have three models: CrewMember (has a name), Episode (has a title, airdate, etc), and Role (has a job title, like Director, Writer or Actor). I could create a table with three fields: CrewMember_ID, Episode_ID, and Role_ID. Each row would then describe someone working on a specific episode in a specific capacity.
So the relationship would appear to be:
CrewMember has_many :episodes
Episode has_many :crew_members
CrewMember has_many :roles
Role has_many :crew_members.
Here's where I get confused. Do I create a new model for that table? And if I do, how exactly do I create instances of that object? I understand relationships like Author has_many :books where I can create a book with Author.books.new, but this kind of has-many has-many has-many thing stumps me a bit.
I can do what I want with SQL, I'm just having trouble approaching it from an ORM/ActiveRecord angle.
you can work around this issue by adding a model that collects the three models
rails g model big_model model1:references model2:references model3:references
Using "Jobs" as GreenTriangle suggested
class CrewMember < ActiveRecord::Base
has_many :jobs, dependent: :destroy, inverse_of: :crew_member
has_many :episodes, through: :jobs
has_many :roles, through: :jobs
end
class Episode < ActiveRecord::Base
has_many :jobs, dependent: :destroy, invserse_of: :episode
has_many :crew_members, through: :jobs
has_many :roles, through: :jobs
end
class Role < ActiveRecord::Base
has_many :jobs, dependent: :destroy, inverse_of: :role
end
class Job < ActiveRecord::Base
belongs_to :episode
belongs_to :role
belongs_to :crew_member
validates_presence_of :episode, :role, :crew_member
end
I have a User model in my application and I'm also creating another object that belongs to a user, lets call it myObject... Now, myObject has one relation to the user that created it and one relation to many users for something else.
How can I have a property in myObject that has a belongs_to relationship with users and is called created_by?
How can I have a property in myObject that has a has_many relationship with users and is called members?
It would look more or less like
User
has_many :memberships
has_many :ownedgroups, :class_name => "Group"
has_many :groups, :through => memberships
Membership
belongs_to :users
belongs_to :groups
Group
has_many :memberships
belongs_to :owner, class_name => "User"
has_many :users, :through => memberships
I would recommend reading Active Record Associations Guide specially their many-to-many parts.
I'm new to Rails and have some doubts about the kind of relationship do I need to use. Here is the case.
I have two models Offer and User, a user could belong to to many offers and offers can have many user. Also the users create the offers.
I think I have to use a has_many :through ralationship. For example I've created another model "Applicant". Applicant belongs_to user and belongs_to offer. But how is the relationship from the user and offer model? For example:
User Model
has_many :offer, :through => :applicant
Offer Model
has_many :user, :through => :applicant
My doubt is because I already have this two relationship
User Model
has_many :offers, :dependent => :destroy
Offer Model
belongs_to :user
After solve this, I guest I have to save the record in the applicant model from the applicanst_controller, right?
Thanks in advance
What you have described is a many-to-many relationship using a join table. You're actually pretty close but you just need to remove the has_many :offers, :dependent => :destroy from your user model and the blongs_to :user in your offer model. It should look something like this:
class User < ActiveRecord::Base
has_many :offers, :through => :applicants
end
class Applicant < ActiveRecord::Base
belongs_to :users
belongs_to :offers
end
class Offer < ActiveRecord::Base
has_many :users, :through => :applicants
end
You don't have to worry about the dependent destroy part as associations are automatically removed as the corresponding objects are removed. With a many to many association it doesn't really matter how you go about building the relationship. Either of the following will work:
#user.offers << #offer
#offers.users << #user
If you don't need to store any information specific to your applicant join table (e.g., time stamps, descriptions) you might instead want to look at a has_and_belongs_to_many relationship. Check out choosing between has_many_through and has_and_belongs_to_many for reference.
Edit
Heres the code for a HABTM relationship:
class User < ActiveRecord::Base
has_and_belongs_to_many :offers
end
class Offer < ActiveRecord::Base
has_and_belongs_to_many :users
end