Write a migration with reference to a model twice - ruby-on-rails

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.

Related

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

belongs_to and has_many to the same model

I am wondering whether there is a way to do this with rails or not. Basically I have a user model and an event model. Event is created by a user and I want to have a foreign key (user_id) in the event model that indicates who created the event. Additionally, event can have many users who attend it so the event model becomes something like
belongs_to :user
has_many :users, :through => :guests #suppose i have the guest model
and the user model looks something like
has_many :events, :through => :guests
I have not tried this association yet but I want to be able to say
e = Event.find(1)
e.creator #returns the user who created this event
instead of
e.user
is there a way for me to do this?
Simply pass some options to belongs_to:
belongs_to :creator, :class_name => "User", :foreign_key => "user_id"
This specifies that the creator method will be a User object, referencing the user_id field.

Ruby on rails - Reference the same model twice?

Is it possible to set up a double relationship in activerecord models via the generate scaffold command?
For example, if I had a User model and a PrivateMessage model, the private_messages table would need to keep track of both the sender and recipient.
Obviously, for a single relationship I would just do this:
ruby script/generate scaffold pm title:string content:string user:references
Is there a similar way to set up two relations?
Also, is there anyway to set up aliases for the relations?
So rather than saying:
#message.user
You can use something like:
#message.sender or #message.recipient
Any advice would be greatly appreciated.
Thanks.
Here's a complete answer to this issue, in case people visiting this question are new to Ruby on Rails and having a hard time putting everything together (as I was when I first looked into this).
Some parts of the solution take place in your Migrations and some in your Models:
Migrations
class CreatePrivateMessages < ActiveRecord::Migration
def change
create_table :private_messages do |t|
t.references :sender
t.references :recipient
end
# Rails 5+ only: add foreign keys
add_foreign_key :private_messages, :users, column: :sender_id, primary_key: :id
add_foreign_key :private_messages, :users, column: :recipient_id, primary_key: :id
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 PrivateMessage < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
belongs_to :recipient, :class_name => 'User'
end
Here you are creating a property on the PrivateMessage model named :sender, then specifying that this property is related to the User class. Rails, seeing the "belongs_to :sender", 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 PrivateMessage model, like this:
#private_message.sender.name
#private_message.recipient.email
Here is your User Model:
class User < ActiveRecord::Base
has_many :sent_private_messages, :class_name => 'PrivateMessage', :foreign_key => 'sender_id'
has_many :received_private_messages, :class_name => 'PrivateMessage', :foreign_key => 'recipient_id'
end
Here you are creating a property on the User Model named :sent_private_messages, specifying that this property is related to the PrivateMessage Model, and that the foreign key on the PrivateMessage model which relates it to this property is called 'sender_id'. Then you are doing the same thing for received private messages.
This allows you to get all of a users sent or received private messages by doing something like this:
#user.sent_private_messages
#user.received_private_messages
Doing either of these will return an array of instances of the PrivateMessage model.
....
Add this to your Model
belongs_to :sender, :class_name => "User"
belongs_to :recipient, :class_name => "User"
And you are able to call #message.sender and #message.recipient and both reference to the User model.
Instead of user:references in your generate command, you'd need sender:references and recipient:references
hi there
to have both side relation do as bellow in your both models:
class Message < ActiveRecord::Base
belongs_to :sender,
:class_name => "User",
:foreign_key => "sender_id"
belongs_to :recipient,
:class_name => "User",
:foreign_key => "recipient_id"
end
class User < ActiveRecord::Base
has_many :sent,
:class_name => "Message",
:foreign_key => "sent_id"
has_many :received,
:class_name => "Message",
:foreign_key => "received_id"
end
I hope this help you...
The above answers, while excellent, do not create foreign key constraints in the database, instead only creating indexes and bigint columns. To ensure that the foreign key constraint is enforced, add the following to your migration:
class CreatePrivateMessages < ActiveRecord::Migration[5.1]
def change
create_table :private_messages do |t|
t.references :sender
t.references :recipient
end
add_foreign_key :private_messages, :users, column: :sender_id, primary_key: :id
add_foreign_key :private_messages, :users, column: :recipient_id, primary_key: :id
end
end
This will ensure that the indices get created on the sender_id and recipient_id as well as the foreign key constraints in the database you're using.

Rails associations with the same models

I have two classes with the following associations:
class Incident
has_one :assignee
has_one :technician
class User
has_many :incidents
Note that the assignee and technician fields refer to objects of type User. How should these relationships be in the model?
Presumably the Incident should belong_to an assignee and technician, because the foreign key holding those relationships would be in the incidents table, not the employees table
class Incident
belongs_to :assignee, :class_name => 'User'
belongs_to :technician, :class_name => 'User'
class User
has_many :assigned_incidents, :class_name => 'Incident', :foreign_key => 'assignee_id'
# not sure the wording you'd want to use for this relationship
has_many :technician_incidents, :class_name => 'Incident', :foreign_key => 'technician_id'
You would want the foreign key fields to be incidents.assignee_id, incidents.technician_id
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 CreateIncidents < ActiveRecord::Migration
create_table :incidents do |t|
def up
t.references :assignee
t.references :technician
end
end
end
Here you are specifying that there are two columns in this table that will be referred to as :assignee and :technician and which hold references to another table. Rails will actually create columns called 'assignee_id' and 'technician_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 Incident < ActiveRecord::Base
belongs_to :assignee, class_name => 'User'
belongs_to :technician, class_name => 'User'
end
Here you are creating a property on the Incident model named :assignee, 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 'assignee_id', which we defined above, and use that to store the foreign key. Then you're doing the exact same thing for the technician.
This will allow you to access your assignee and technician, both instances of the User model, through an instance of the Incident model, like this:
Incident.assignee.name
Incident.technician.email
Here is your User Model:
class User < ActiveRecord::Base
has_many :assigned_incidents, :class_name => 'Incident', :foreign_key => 'assignee_id'
has_many :incidents_as_technician, :class_name => 'Incident', :foreign_key => 'technician_id'
end
Here you are creating a property on the User Model named :assigned_incidents, specifying that this property will be referencing instances of the Incident Model, and that the foreign key on the Incident model which references this, the User Model, that we want to use to for this property is called 'assignee_id'. Then you are doing the same thing for incidents_as_technician (this naming seems kind of awkward, but without better knowledge of what you're trying to do, I don't really have any great suggestions).
This allows you to get all of a user's assigned incidents or incidents as technician by doing this:
User.assigned_incidents
User.incidents_as_technician
Doing either of these will return an array of instances of the Incident model.

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