help with rails associations - ruby-on-rails

I want to implement a messaging system for my app.
I have users.
What exactly should I do?
create a messages model with foreign two user foreign keys??.. what would be the most approproate way of getting this done?
My worry is that if I query "message.user" I wont know if Id be getting the sender of the receiver of the message

Use two separate foreign keys with approprately named belongs_to relations to distinguish between senders and receivers.
Given a message model with the foreign keys sender_id and receiver_id you can do:
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => "User", :foreign_key => "sender_id"
belongs_to :receiver, :class_name => "User", :foreign_key => "receiver_id"
end
Now you'll be able to reference a message's sender using message.sender and receiver using message.receiver.

Related

Which model association for messages and many users

Im new to Rails and actually im trying to write my own messaging application. So far i have many users with username, password, etc. And now im figuering out how i should best write the migration for the message model. I thought that a message needs:
Message
sender_id => integer
recipent_id => integer
created_at => time
updated_at => time
The first problem im facing is that of course sender_id is unique but what is with recipent_id, there are often messages that should go to several people!
Next problem is i dont know how i have to refer form the user model to the message model i mean normaly i would write:
User has_many :messages
Message belongs_to :user
To do this i would need a coulmn named user_id in the message model , but now i have two cloumns sender_id and reciepent_id!
I hope you can give my some hints! Thanks
Is this what you are looking for?
class User < ActiveRecord::Base
has_many :messages, :foreign_key => "sender_id" #this only gives the messages sent by the user.
end
class Message < ActiveRecord::Base
#sender_id
belongs_to :sender, :class => "User", :foreign_key => "sender_id"
has_many :recipients, :class => "MessageRecipient"
end
class MessageRecipient < ActiveRecord::Base
belongs_to :message
belongs_to :recipient, :class => "User", :foreign_key => "recipient_id"
end
If you want to get all the recipients for the message, you could do
message.recipients.collect(&:email)

Write a migration with reference to a model twice

I have a message model (Message) and this models as a userTo and userFrom, so two references to User. How can i write the migration? My user model is User.
Thank you
Here's a complete answer to this issue, in case people visiting this question are having a hard time putting everything together (as I was when I first looked into this).
Some parts of the answer take place in your Migrations and some in your Models:
Migrations
class CreateMessages < ActiveRecord::Migration
create_table :messages do |t|
def up
t.references :sender
t.references :recipient
end
end
end
Here you are specifying that there are two columns in this table that will be referred to as :sender and :recipient and which hold references to another table. Rails will actually create columns called 'sender_id' and 'recipient_id' for you. In our case they will each reference rows in the Users table, but we specify that in the models, not in the migrations.
Models
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
belongs_to :recipient, :class_name => 'User'
end
Here you are creating a property on the Message model named :sender, then specifying that this property will be referencing an instance of the User class. Rails, seeing the "belongs_to", will look for a column in your database called "sender_id", which we defined above, and use that to store the foreign key. Then you're doing the exact same thing for the recipient.
This will allow you to access your Sender and Recipient, both instances of the User model, through an instance of the Message model, like this:
#message.sender.name
#message.recipient.email
Here is your User Model:
class User < ActiveRecord::Base
has_many :sent_messages, :class_name => 'Message', :foreign_key => 'sender_id'
has_many :received_messages, :class_name => 'Message', :foreign_key => 'recipient_id'
end
Here you are creating a property on the User Model named :sent_messages, specifying that this property is related to the Message Model, and that the foreign key on the Message model which relates to this property is called 'sender_id'. Then you are doing the same thing for received messages.
This allows you to get all of a users sent or received messages by doing something like this:
#user.sent_messages
#user.received_messages
Doing either of these will return an array of instances of the Message model.
In the migration, create two different columns for each kind of user. For example:
add_column :messages, :sender_id, :integer
add_column :messages, :receiver_id, :integer
Then in the model, that's where the logic to map each column to the User class happens:
belongs_to :sender, :class_name => 'User'
belongs_to :receiver, :class_name => 'User'
Of course, use your own words for sender and receiver, but Rails will automatically associate sender to the sender_id column (and the same logic for receiver)
You will then be able to interact with both user user.sender and user.receiver.

How can I relate to an object twice in rails?

I've got a Users model and a Tasks model.
A task has a creator, of type user, and an assignee of type user.
I've already done a migration of AddUserIdtoTasks to get the creator relation working, but now I need to do the same thing again to add the assignee, but I'm already using the keyword 'user'. How should I go about building a proper relation.
A task only has one assignee, always.
I'm using devise for the user model.
has_one :creator, :class_name => "User"
has_one :asignee, :class_name => "User"
Or belongs_to, depending on how your fields are set up. has_one and belongs_to both take an optional :class_name argument for cases just such as yours.
Create the field assignee_id in your Task model and then use it for the relation as in
class Task < AR::Base
belongs_to :assignee, :class_name => 'User'
end
On the other side of the relation
class User < AR::Base
has_many: :assigned_tasks, :class_name => 'Task', :foreign_key => :assignee_id
end
Sorry, should be :class_name. Updated User class also with a :foreign_key parameter, without it user.assigned_tasks would have joined records using the :user_id parameter (the default value for has_many, i.e. "#{class_name}_id"`).
I invite you to read the link I've posted, it explains better than me all these things.
Source: http://guides.rubyonrails.org/association_basics.html#detailed-association-reference

Multipe relationships in Rails where the class name does not match the association name

I have a private message model that relates to two users, how do I setup an association so that PM.sender is the sender's user model and PM.receiver is recipient's user model? (so that I can call PM.sender.username etc.)
I have a sender_id and receiver_id field.
Assuming model classes Message and User, in your Message model:
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
belongs_to :receiver, :class_name => 'User'
end
Because the class name can't be deduced from the association name the explicit :class_name is required.
Update: Having just checked, the :foreign_key parameter shouldn't be required as long as the name of the foreign key is the name of the association followed by _id, which it is in this case.

Two foreign keys with ActiveRecord? [rails]

I have a User class with reference to a Message class. The message class has a user_id (which is the sender) and a receiver_id. So in the User class I have
has_many :messages
has_many :messages, :foreign_key => "receiver_id"
and then in the Message class I have
belongs_to :user
The first relationship -- via user_id -- goes perfectly well. I haven't the slightest idea what to put in the Message class for the second relationship. The messages table is built with both user_id and receiver_id, so the support is there.
Is this even possible?
Also, then I'd have no idea how to get to the messages RECEIVED by a user... or the User who received a message :)
[I know that I can work around this by having a sender table and a receiver table and a messages table and maybe a bunch of other tables (a conversations table!), but I'd like to do it like this, for the fun of it. This application will be used for learning only.]
Also important: where would the docs be for this? This is not very helpful.
In your User class:
has_many :messages
has_many :received_messages,
:foreign_key => "receiver_id", :class_name => "Message"
In your Message class:
belongs_to :user
belongs_to :receiver, :class_name => "User"
#user = User.first
#user.messages
#user.received_messages

Resources