ActiveRecord::Base.connection.tables
["groups", "groups_users", "members", "questions", "users", "votes", "schema_migrations"]
As you can tell, I have a table named, "groups_users" yet I cannot seem to access it. I can access the "users" table by User. I can access the "groups" table by Group. But how exactly do I access "groups_users"? I have tried:
Groups_Users
Groups_User
GroupsUsers
GroupsUser
I have also tried the singular version of Groups. Any ideas on how to access it? Documentation would also help.
Group
class Group < ActiveRecord::Base
has_and_belongs_to_many :users
end
User
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
end
You have to define a model for groups_users table if you want to access it
class GroupUser < ActiveRecord::Base
self.table_name = "groups_users"
belongs_to :user
belongs_to :group
end
You can also define your associations like this
class Group < ActiveRecord::Base
has_many :group_users
has_many :users, :through => :group_users
end
class User< ActiveRecord::Base
has_many :group_users
has_many :groups, :through => :group_users
end
You can read about the difference here
Vimsha's answer is the right one; I'd also share my experiences with HABTM vs HMT for you:
HABTM is only for if you have "non-accessible" data. Rails' join
engine treats HABTM as having no model, and consequently you can't access the data directly. HMT (has_many :through) works by having a model & then allowing you access to it
The difference between HABTM & HMT is basically the direct access through the model. HABTM is there for "quick and dirty" collection access; HMT is there for more substancial data access
You need to create a model.
class GroupsUsers < ActiveRecord::Base
end
Related
I have a model User and a model Group, between the two I want to create a many-to-many association with a join-table, using through.
user.rb:
class User < ActiveRecord::Base
has_many :groups_user
has_many :groups, :through => :groups_user
end
group.rb:
class Group < ActiveRecord::Base
has_many :groups_user
has_many :users, :through => :groups_user
end
groups_user.rb
class GroupsUser < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
I initially tried to do the same thing naming the joining model class GroupsUsers in groups_users.rb but I got an uninitialized constant error unless I used :class_name to specify the class name.
My question is: What is the logic behind pluralizing the first name, but not the second? The association is many-to-many so both models are on equal footing. In this case group comes first merely because of the lexical order. So why pluralize one and not the other? This makes no sense to me.
The more conventional naming approach would be:
#user.rb:
class User < ActiveRecord::Base
has_many :group_users
has_many :groups, :through => :group_users
end
#group.rb:
class Group < ActiveRecord::Base
has_many :group_users
has_many :users, :through => :group_users
end
#group_user.rb
class GroupUser < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
Conventionally, the model has the singular form. So GroupsUser, not GroupsUsers. But, an instance of the join model has only one Group and one User, So, GroupUser, not GroupsUser.
If you look at the The has_many :through Association section of the Active Record Associations guide, for instance, you will see that the join model (Appointment) is singular. This is the pattern you want to follow.
If you decide to do things unconventionally, then rails needs you to help it - for instance by requiring that you specify class_name.
So I have two tables, a Customers table and a Companies table. I have also created an empty Employees table that I would like to use as a join table.
These are the associations I have: (I want customers to be associated with their respective company)
class Company < ApplicationRecord
has_many :employees
has_many :customers, :through => :employees
end
class Customer < ApplicationRecord
belongs_to :employees
end
class Employee < ApplicationRecord
belongs_to :customer
belongs_to :company
end
Where would be the best way to do this? In my Customer#new method in the controller? I read that I need to use <<, but I don't know how to approach that.
You need to use the concept of Inverse association here:
class Customer has_many :companies, :through => :employees
You could just try delegating the company call on customers to their employee:
customer.rb
delegate :company, to: :employee
Now whenever you ask a customer its company, it will ask its employee to handle it.
If I have a legacy database where I the relationships between 2 entities are defined in a different table. How do I create that relationship in rails?
The basic relationship I want to present is:
---Admins:
First_name
Last_name
id
---Sites:
id
subject
---Admin_Sites
id
teacher_id
class_id
I know in rails I would just use belongs_to: and has_many: but if I have a (constantly updated) teach_class table, I need to somehow specify that THAT's where rails need to look for the relationship of who is related to which class. I am at a loss how I can specify this. Is it possible to somehow specify :foreign_key as "teach_class.teacher_id" in classes model?
In Teacher Model you would have
has_many :teach_classes
has_many :classes, :through => :teach_classes
see this blog for has_many :through relationship - http://ruby-on-rails-dipak-panchal.blogspot.in/2012/10/has-many-through-relationship.html
class Admin < ActiveRecord::Base
has_many :admin_sites
has_many :sites, :through => :admin_sites
end
class Site < ActiveRecord::Base
has_many :admin_sites
has_many :admins, :through => :admin_sites
end
class AdminSites < ActiveRecord::Base
belongs_to :admin
belongs_to :site
end
I'm working on Ruby on rails 2.3.8, and I'd like to build a functionality to follow users.
For this purpose, I've created 2 tables: users and followings, with their respective models:
class User < ActiveRecord::Base
has_and_belongs_to_many :followings, :foreign_key => "follower_id"
end
class Following < ActiveRecord::Base
has_and_belongs_to_many :users, :foreign_key => "follower_id", :class_name => "User"
end
Now, when I try to execute current_user.followings.all (with a valid current_user, of course), it throws me the following exception:
'followings_users' doesn't exist: SELECT 'followings'.* FROM `followings` INNER JOIN 'followings_users' ON 'followings'.id = 'followings_users'.following_id WHERE ('followings_users'.follower_id = 1 )
I can't make this work. I don't know why it asks me for a "followings_users" table. What if I want to call it just "followings"?
What am I doing wrong here?
When using habtm, Rails will try to get the associations from a join table. It tries to guess the name of the table by joining the two names (followings_users), or you can specify the name of the table as an option. But you have to explicitely create this table in your migrations.
See documentation here
You can also do this using the newer syntax has_many :through:
class User < ActiveRecord::Base
has_many :user_followings
has_many :followings, :through => :user_followings
end
class UserFollowing < ActiveRecord::Base
belongs_to :users
belongs_to :followings
end
class Following < ActiveRecord::Base
end
This requires a join table called :user_followings with columns user_id and following_id.
The new syntax is generally preferred over HABTM because it allows you to define methods on the join model, which can be useful, although HABTM still works fine as well.
I have two models, Users and Groups. Each group can have many users and each user can be in many groups.
I currently have something simple like:
User:
has_many :groups
Group:
has_many :users
So I have a groups_users table which is just creating rows with group_id and user_id.
I want to add another column to this, (which I have), the question is how do I access it from a model without using a custom SQL call? In the group model I can go self.users and in user I can go self.groups
Is there a way to change the third column in this table from a user model?
Sorry if this is confusing, please advise on this
Here are a couple of tutorials that should help. Basically there two approaches to make many-to-many work, either has_and_belongs_to_many or has_many :through (recommended).
links:
http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off
http://railscasts.com/episodes/47-two-many-to-many
http://railscasts.com/episodes/154-polymorphic-association
In Rails 3 you want to make a join table for many to many relationships, using the plural names of the tables you want to join in alphabetical order. So in this case it would be groups_users.
models
class GroupsUser < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
class User < ActiveRecord::Base
has_many :groups_users
has_many :groups, :through => :groups_users
end
class Group < ActiveRecord::Base
has_many :groups_users
has_many :users, :through => :groups_users
end
I [added] another column to [users_groups]...The question is how do
I access it from a model without using
a custom SQL call?
It sounds like you want to access a column of your user_groups table by calling a method on your User model or your Group model.
Some suggestions:
I'd name the table "user_groups" to work with ActiveRecord's pluralization expectations, but I'm not sure if that's essential.
Following Dave's advice, you'd want to set things up using the "has_many :through" technique...
# Declare a Model based on the many-to-many linking table.
class UserGroup < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
class User < ActiveRecord::Base
has_many :user_groups
has_many :groups, :through => :user_groups
end
class Group < ActiveRecord::Base
has_many :user_groups
has_many :users, :through => :user_groups
end
Is there a way to change the third column in this table from a user model?
This is a little unclear, but keep in mind that each User can have a lot of UserGroups. So if you wanted to change that third column you'd have to find the particular one you're looking for.