Rails 5 - model with 2 fields referring to same object - ruby-on-rails

In the app I am building to learn RoR, I have a model "Document" and a model "Business Partner". On the "Document" model, I have 2 fields ("Sender" and "Receiver") referring to the model "Business Partner".
How do I model twice a belongs_to the same target with different fields? What should the migration be?
Related question: how do I model the relationship to it self for business partner? i.e. one company has many business partners, yet can be a business partner too. Note - not to the same record (company A cannot have a relationship to company A (itself).

Assuming you've got columns sender_id and receiver_id for the sender and receiver relationships on your Document model (i.e. on your documents table), you can do something like this:
class Document < ActiveRecord::Base
belongs_to :sender, class_name: "BusinessPartner"
belongs_to :receiver, class_name: "BusinessPartner"
end
There's no particular migration for this as long as you've got those columns there on the table (if you've named them something else, just replace sender and receiver above by whatever column name minus the _id part).
And then for your BusinessPartner model:
class BusinessPartner < ActiveRecord::Base
has_many :sent_documents, class_name: "Document", foreign_key: "sender_id"
has_many :received_documents, class_name: "Document", foreign_key: "receiver_id"
end
Here, sent_documents will fetch all rows in the documents table where sender_id matches the id of the BusinessPartner, and similar for received_documents.
More info in the Rails docs.
Regarding your second question, there is a section of the Rails docs describing this, it is called "Self Joins". However, given that you want to model a many-to-many relationship, you will need a slightly special table arrangement. See this SO answer for some details on how to setup that arrangement. That is actually a somewhat tricky topic in itself, if you're interested in details I'd recommend asking a separate question on it (although that SO post answers it pretty well).

Related

Get association from custom name

My Seminar model has a column named teacher_id. That part of the relationship is working. I can call seminar.teacher to retrieve the User who teaches that seminar.
I'd like to be able to invert that query. In other words, I need to call teacher.own_seminars to get a collection of all the seminars where that User is listed as the teacher_id. I know that I could call Seminar.where(:teacher => teacher), but that's clunky. And I think that the performance is probably worse that way.
Note: Some of the Users are students who are linked to Seminar through the seminar_user join table, but I don't think that affects this question.
This is the model setup that isn't quite working yet
class User < ApplicationRecord
has_many :own_seminars, :class_name => "Seminar", foreign_key: 'own_seminar_ids'
end
class Seminar < ApplicationRecord
belongs_to :teacher, class_name: "User", foreign_key: 'teacher_id'
end
Cheers!
In foreign_key option, you specify the column which is, well, the foreign key.
The way has_many works, is it tries to guess, which one of the fields in the referenced entity corresponds to the primary key of this entity. By default, it's user_id (derived from name User). But since your column is actually called teacher_id, you should use that instead.
has_many :own_seminars,
class_name: "Seminar",
foreign_key: 'teacher_id'

Can a Rails Model have an array of associations?

I've looked everywhere, and can't find anything (maybe cause it's not possible)
I have a Meeting model and a Language model (which has a string column called language). Each Meeting has 2 Languages.
Is there a way to make an association, such as:
rails g migration AddLanguageToMeetings language:references
And then store an array of 2 language_ids in the reference?
For example, Meeting.language_id = [1,2]
And then be able to call the Language, like:
meeting.language_id[0].language
How can I se up this association? Do I need to have 2 different columns with each associated id?
Thanks!!
What you want is a N-to-N relation. Create another model called MeetingLanguage with two columns:
create_table :meeting_languages do |t|
t.references :meetings
t.references :languages
end
and associations:
class MeetingLanugage < ActiveRecord::Base
belongs_to :language
belongs_to :meeting
end
And then in Meeting module:
has_many :meeting_languages
has_many :languages, through: :meeting_languages, source: :language
Now you can have as many languages as you want for a single meeting.
What you're describing is a has_many, where the foreign key exists in the languages table, or in a joining table between the languages and meetings tables.
If you want each Meeting to point two exactly two Languages, then you can use two foreign keys in the meetings table, give each language a real name, and then have two belongs_to associations in your Meeting.

Rails relationship based on common field

I've found quite a few topics on ActiveRecord has_many relationships, but I haven't found exactly what I am looking for.
I've got two tables that each have the column xyz_id. This id is a corresponding ID in an API service I'm subscribed to.
I want to have a has_many relationship through these corresponding ids in the corresponding columns on each table. Such that, if an item in table_1 has an xyz_id of "abcdefg", I can do something like table_1.relation and it will return all elements in table_2 with a matching xyz_id. I could leverage ActiveRecord throughout my code and utilize queries, but I think there has to be a better way. Any thoughts?
EDIT: I a word.
ActiveRecord lets you specify arbitrary fkeys when you define the relationship, like so:
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts,
foreign_key: :xyz_id
end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies,
foreign_key: :xyz_id
end
Source: http://guides.rubyonrails.org/association_basics.html

Ruby on Rails model associations

New in rails here. I have trouble understanding this specific activerecord association. Can someone help me on this. The model looks like this:
class User < ActiveRecord::Base
has_many :client_occurrences,
foreign_key: "client_id",
class_name: "Occurrence"
has_many :requested_occurrences,
foreign_key: "requestor_id",
class_name: "Occurrence"
end
And the one it's associated to is:
class Occurrence < ActiveRecord::Base
belongs_to :template, autosave: true
belongs_to :requestor, class_name: "User"
belongs_to :client, class_name: "User"
end
I just can't seem to understand the associations being portrayed here. Everytime I see the user model, I immediately classify it as an issue because here's how I read the association in the user model:
User has many occurrences alias by client_occurrences and set
client_id as foreign_key
It's an issue for me since the foreign_key is not in the proper table (According to my understanding of the code). In addition, client_id and requestor_id are columns found in the Occurrence table.
Could anyone help?
I'm not sure where your issues are. I would say your reading is correct, namely:
User does have many Occurences (each Occurence points back to
the User)
They are aliased/referenced as client_occurrences from
the perspective of the User The foreign_key is indeed
client_id.
That is, the Occurence table uses client_id to point
to the User
From the point of view of Occurrence:
Each Occurrence belongs to a :client, which means the field name will be client_id (which matches the foreign_key clause in the User model)
The item being pointed to is really a User
One of the things that's confusing, I think, is that the order of the has_many clauses is different from the order of the corresponding belongs_to clauses.
These are the business rules I gather from that:
A User can be associated with an Occurrence as a client
A User can be associated with an Occurrence as a requestor
A User can be associated to many Occurrences
An Occurrence has one requestor User, and one client User
The foreign key is specified in the User model because it's associated to the same model multiple times, otherwise rails would default to using "user_id" as the foreign key in the Occurrence model.
Check this link out for the full details on what all the different ActiveRecord Associations do:
Rails Guides: ActiveRecord Associations

Database association, Case model has two People

I got a case model. This case model has a client and an opponent field.
Both of them are Person models. A case has exactly one client and one opponent. Now a Person can be a client or it could be an opponent and a Person can have many cases.
How can i build this association in rails? When i split the Person model into a client and an opponent model it seems quite easy, but that does not seems very dry to me.
This is what i have at the moment
class Person < ActiveRecord::Base
has_many :cases
end
class Case < ActiveRecord::Base
belongs_to :client, class_name: 'Person'
belongs_to :opponent, class_name: 'Person'
end
This works so far, that i can add clients and opponents to a case.
But how can i find all the cases through a client or an opponent?
---old
when i have Client.first.cases my sql query is:
--new
of course i mean Person.first.cases-- since i dont have a clients table, just my id inside the Case table is called client_id or opponent_id
SELECT cases.* FROM cases WHERE cases.person_id = 3
Now this has to be the client id or the opponent id
Thanks for help
When you asks for Client.first.cases, In this query Active Record understand, you want all cases to be fetched that belongs to Person table's first record (which id is 3).
person_id is client_id, because first client's id in your person table is 3.
If you will write : Client.first, In your sql query you will see :
SELECT person.* FROM person WHERE person_id = 3
I think, you should try to pass a foreign_key constraint in you Case model like this:
class Case < ActiveRecord::Base
belongs_to :client, class_name: 'Person', foreign_key: "client_id"
belongs_to :opponent, class_name: 'Person',foreign_key: "opponent_id"
end
Thanks.
(~ last 10 minutes of) http://www.youtube.com/watch?v=AhFK0UO9VPs ~
Here is almost the explanation of my problem with a Person model and a Message model, where the Message Model has a receiver_id and a sender_id.
The foreign key is not needed at the Case model (to go back to my question), it is needed inside the Person model like this
class Person < ActiveRecord::Base
has_many :cases, foreign_key: "client_id"
end
so on a Person object i can use not person.cases and i will get all the cases, where this person is the client.
I still don't know, how to get the cases, where the person is the opponent

Resources