rails, model naming question - ruby-on-rails

I'm creating a model called Chats. And I want to assign users to a discussion. They are either a part of the Chats or they aren't...
So I create one model Chats.
What's the standard Rails naming convention for the other table?
ChatUsers?

While has_and_belongs_to_many is an ok option here, I recommend going with has_many :through instead.
In essence you will have an explicit join model, which you can call something like ChatSession.
class Chat < ActiveRecord::Base
has_many :chat_sessions
has_many :users, :through => :chat_sessions
end
class User < ActiveRecord::Base
has_many :chat_sessions
has_many :chats, :through => :chat_sessions
end
class ChatSession < ActiveRecord::Base
belongs_to :user
belongs_to :chat
end
Now you will need a table called chat_sessions with columns :user_id, and :chat_id in it. This is your join table.
Advantage
You get a model which is fully under your control, and isn't just a dumb join table managed by rails. So for example, if you want to track number of messages particular user left in particular chat, it could be a column in chat_sessions table. Presence of :through renders habtm unneeded in most cases. There is no complexity overhead either.

If it is a join table, it would be both table names joined by '_' and in alphabetical order of table names:
chats_users

This is called a has_and_belongs_to_many association in rails. You basically have two models that call has_and_belongs_to_many and create a linking table that uses the two models in the name (alphabetical and plural).
models:
class Chat < ActiveRecord::Base
has_and_belongs_to_many :users
end
class user < ActiveRecord::Base
has_and_belongs_to_many :chats
end
Then your tables would be
chats
users
chats_users

Related

Order HABTM associations by created_at on the association instead of the object

I have a Match and User model with a has_and_belongs_to_many between them.
How do I retrieve match.users.first and match.users.second based on when the MatchUser association was created, rather than by when the User itself was created?
You don't want to be using has_and_belongs_to_many in the first place. has_and_belongs_to_many relations are headless - there is no join model. The only columns that are ever used on the join table are the two foreign keys. Even if you added a created_at column to the join table there is no way to access it or use it to order the records. And AR won't set the timestamps anyways.
While you can kind of assume that a has_and_belongs_to_many association is ordered in the same order that the records where inserted you can't really order it.
You want to use has_many through: which uses a model to join the two records:
class User < ApplicationRecord
has_many :user_matches
has_many :matches, through: :user_matches
end
class Match < ApplicationRecord
has_many :user_matches
has_many :users, through: :user_matches
end
class UserMatch < ApplicationRecord
belongs_to :user
belongs_to :match
end
You can then order the association by:
match.users.order("user_matches.created_at DESC")
match.users.first
will return the first user by :id.
If you want to it ordered by created_at then you must do something like
user_id = matches_users.where(match_id: match.id).first.user_id
user.find(user_id)
Hope this is what you are looking at.

Rails migration join table for multiple associations of the same model using different names

In my project, I have this simple association set up:
class Episode < ActiveRecord::Base
belongs_to :game_master, :class_name => 'CastMember'
has_and_belongs_to_many :players, :class_name => 'CastMember'
end
class CastMember < ActiveRecord::Base
has_and_belongs_to_many :episodes
end
I was wondering what the join table for these might be.
At first, I thought a cast_members_episodes table would be enough, but after thinking about it for a bit, it wouldn't make sense, as it wouldn't be able to differentiate between game_master and players.
Any ideas?
Yes, cast_members_episodes table to handle the many-to-many relation of players and episodes.
And, add a column game_master_id to episodes table to handle the relation of game_master and episodes.

Double entry table in rails

I would like to create a double entry table form according two models.
For now I'm able to create a simple table with the members of a communities
on the columns, I must add the informations of an other model, like this :
My models :
Community
has_many :memberships
Membership
belongs_to :user
belongs_to :community
User
has_many ::memberships
has_many :skills
Skill
belongs_to :user
belongs_to :community
I there some gem existing to make a double entry table or is it easier to make it from scratch? if so, how can I begin ?
It seems like you would benefit from a through relationship here.
Instead of referencing community directly from the skill table, you could do:
Skill
belongs_to :user
has_many :communities, :through => :user
On user, add:
has_many :communities, :through => :memberships
Wouldn't this get the link between skill and community that you would like?
As Jay mentioned, you would benefit from a has_many :through relationship, or maybe a has_and_belongs_to_many relationship; whether it's the actual solution we'll have to see:
#app/models/user.rb
Class user < ActiveRecord::Base
has_many :memberships
has_many :skill_users
has_many :skills, through: :skill_users
end
#app/models/skill_user.rb
Class SkillUser < ActiveRecord::Base
belongs_to :skill
belongs_to :user
end
#app/models/skill.rb
Class Skill < ActiveRecord::Base
has_many :skill_users
has_many :users, through: :skill_users
end
This will allow you to associate each user (note that members are different than users) with specific skills without using double-entries in your tables
Relational
The basis of what you're seeking can be found in Relational Databases
These work by storing data in single instances, and linking to other data through foreign_keys. These foreign keys are things such as user_id etc:
(more information here)
This means instead of populating the same data twice, it is correct to reference that data from other models, as required. This is where join models come in
Join Model
Join models allow you to "link" two pieces of data through a join model:
For you, it means storing your skills in its own model, and linking users with skills on a join model (I've called skill_user.rb). This means that you'll be able to call your user's skills like this:
#user.skills #-> goes through the join model

How to correctly search models with a join table in rails?

I am trying to set up my models and controllers for a user event setup. It's a many-to-many setup for users to sign up for events. I already have the join table ('users_events') created.
So far I have:
Models:
class User < ActiveRecord::Base
has_and_belongs_to_many :events, join_table: 'users_events'
end
class Event < ActiveRecord::Base
has_and_belongs_to_many :users, join_table: 'users_events'
end
I want to be able to be able to query for all events a user is signed up for. Where should this query go? In users_controller or events_controller? What would the search/find code look like?
First of all users_events goes against rails convention. Rails infers table names by alphabetical order so the table should be named: events_users
Then you can do things like:
current_user.events
Or
event = Event.create!(name: "foo")
current_user.events << event
And the other way around..this way you also don't need to mention the join table in your model.
I was able to figure it out. As I elaborated in my reply to Nikolai, I also have a one-to-many relationship in that an event belongs_to (was created by) a user, so user.events was giving me the events the user had created, not what they were attending. Here is how I solved it.
class User < ActiveRecord::Base
has_many :events
has_and_belongs_to_many :attending_events, class_name: 'Event'
end
class Event < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :attendees, class_name: 'User'
end

Rails (ActiveRecord) many to many table

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.

Resources