Rails self referential data - ruby-on-rails

I currently have a model named Skill. I want skills to have the possibilities have having parents and children skills.
What I currently have:
class Skill < ActiveRecord::Base
has_many :children, foreign_key: :parent_id, class_name: Skill
has_many :parents, foreign_key: :child_id, class_name: Skill
end
However, this is not picking up on the join table that I have created for this (skill_relations).
How would I either specify the table that I have created, or what should the proper name of the join table so that rails can pick this relationship up automatically?

When you use has_many, Rails assumes that the associated table is derivable from the symbol you've provided (e.g. the table children for :children).
If you want to have a separate "relations" table, you specify it with the through parameter, as in:
has_many :children, foreign_key: :parent_id, through: :skill_relations
has_many :parents, foreign_key: :child_id, through: :skill_relations

Related

has_many :through within same model

I have User model in my database. It has role. role can be either patient or doctor. I want to maintain doctor_patient table.
doctor_patient.rb
belongs_to :doctor, class_name: 'User'
belongs_to :patient, class_name: 'User'
a patient can belong to many doctors and a docor can have many patients. I am familier to regular or normal has_many through association but facing issues related to this scenarios where I have role in user model.
user.rb
user
has_many :doctor_patients
has_many :patients, :through => :doctor_patients, :class_name=> "User"
patient
has_many :doctor_patients
has_many :doctors, :through=> :doctor_patients, :class_name=> "User"
In ActiveRecord the assocation metadata (the reflection) is strored in a class attribute as a hash and the name is used as the key. So when you define multiple assocations with the same name you're just overwriting your previous assocation.
The solution is to use unique names for each assocation:
class User < ApplicationController
has_many :doctor_patients_as_doctor,
foreign_key: :doctor_id,
class_name: 'DoctorPatient'
has_many :patients,
through: :doctor_patients_as_doctor
has_many :doctor_patients_as_patient,
foreign_key: :patient_id,
class_name: 'DoctorPatient'
has_many :doctors,
through: :doctor_patients_as_patient
end
Also make sure you pluralize the table correctly and name it doctor_patients.

has_many :through with class_name and foreign_key not working

i need to create parental relation i.e child and parent relation within a customer model. For storing information about parent and child, i have created a join table i.e ParentalRelation.
My customer model is:
class Customer < ApplicationRecord
has_many :parental_relations
has_many :children, class_name: 'Customer', foreign_key: 'child_id', through: :parental_relations
has_one :parent, foreign_key: 'parent_id', class_name: 'Customer', through: :parental_relations, source: :parent
end
My parental_relation model is:
class ParentalRelation < ApplicationRecord
belongs_to :parent, class_name: 'Customer'
belongs_to :child, class_name: 'Customer'
end
I am trying to get data by:
Customer.first.children
But i am not getting data. getting like this even when there is data:
Customer::ActiveRecord_Associations_CollectionProxy:0x3fe49a819750
It would be really great help if anybody could help me out. Thank you in advance
if parent_relation has column parent_id and child_id
I believe it should be
class Customer < ApplicationRecord
has_many :children_relations, class_name: 'ParentalRelation', foreign_key: 'parent_id'
has_many :children, class_name: 'Customer', foreign_key: 'parent_id', through: :children_relations, source: :child
has_one :parent_relation, class_name: 'ParentalRelation', foreign_key: 'child_id'
has_one :parent, foreign_key: 'parent_id', class_name: 'Customer', through: :parent_relation, source: :parent
end
according to your relation, Rails will excute sql SELECT "customers".* FROM "customers" INNER JOIN "parental_relations" ON "customers"."id" = "parental_relations"."child_id" WHERE "parental_relations"."customer_id" = $1 LIMIT $2
But I don't know your table struct. So you can read the sql in rails console and find out how Rails find records. It should help you to solve this problem.
Given you have customer has_one :parent in your model, it looks like you are trying to create a one-to-many relationship. If this is correct, you don't need a join table. You only need a join table if you are creating a many-to-many relationship.
To do this as a one-to-many, remove the ParentalRelation model and table and update your customer class to something like this:
class Customer < ApplicationRecord
belongs_to parent, class_name: "Customer"
has_many children, class_name: "Customer", foreign_key: :parent_id
end
Check out the guides here for creating a self joining table:
https://guides.rubyonrails.org/association_basics.html#self-joins
Once you have that, you should be able to do this:
Customer.first.children

Rails association with multiple custom field names?

I have Members and Skills tables.
Each member record has 3 links to a skill: skill_primary, skill_secondary and skill_tertiary.
Each of those columns is just an ID that corresponds to a row in the Skills table.
What I want to be able to do is is reference a members given skill and get that record from the sills table.
So: member.skill_primary would return the actual Skill record.
What type of associations would I set up to pull that off?
To do this you need to declare 3 belongs_to associations and use the :class_name and :foreign_key options.
class Member < ActiveRecord::Base
belongs_to :skill_primary, class_name: 'Skill', foreign_key: :skill_primary
belongs_to :skill_secondary, class_name: 'Skill', foreign_key: :skill_secondary
belongs_to :skill_tertiary, class_name: 'Skill', foreign_key: :skill_tertiary
end
For documentation on these options, see section 4.1.2 of the Rails Guide for Active Record Associations: http://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference

Rails: Single-table inheritance with many-to-many self-join relationships between records

I am modeling a learning web app with two distinct roles, Teachers and Students. There is a lot of common behaviour between both and it makes sense to abstract them to an AppUser base class. It also helps to use single-table inheritance for the two models, with a single table app_users storing both types.
Now a Teacher can have many Students, and a Student could be enrolled in courses by many different Teachers. So it's a proper many-to-many relationship. How may I model a many-to-many relationship between records in a single table.
I think one option is to use a join table on AppUser - something like app_users_app_users, with a teacher_id and a student_id column. What's the syntax to define this?
An alternative is to use a model, like AppUserRelationship, and then define has_many through relations. What's the way to do this?
this just an idea, create new relation table to hold many to many relation between
class Relation < ActiveRecord::Base
belongs_to :student, foreign_key: "student_id", class_name: "User"
belongs_to :teacher, foreign_key: "teacher_id", class_name: "User"
end
class User < ActiveRecord::Base
# as teacher
has_many :student_relations, foreign_key: :teacher_id, class_name: "Relation"
has_many :students, through: :student_relations, source: :student
# as student
has_many :teacher_relations, foreign_key: :student_id, class_name: "Relation"
has_many :teachers, through: :teacher_relations, source: :teacher
end

rails HABTM to has many through

class QuestionSet
has_and_belongs_to_many :questions,
class_name: 'Exam',
join_table: 'question_question_sets',
foreign_key: 'question_set_id',
association_foreign_key: 'question_id'
end
class Question
has_and_belongs_to_many :question_sets,
class_name: 'Exam',
join_table: 'question_question_sets',
foreign_key: 'question_id',
association_foreign_key: 'question_set_id'
end
The above models are inherited from the base model Exam(using rails STI) and the join table contains two fields: question_id and question_set_id. Now I need to convert this association into has_many through.
I have tried as follows:
class QuestionQuestionSet
has_many :questions
has_many :question_sets
end
class Question
has_many :question_question_sets, foreign_key: :question_id
has_many :question_sets, through: :question_question_sets
end
class QuestionSet
has_many :question_question_sets, foreign_key: :question_set_id
has_many :questions, through: :question_question_sets
end
Even after editing your models, it's necessary to create a new join table since the previous one (created by habtm) doesn't have and "id" column.
As a reference you can follow the steps indicated in http://www.chrisrolle.com/en/blog/migration-path-from-habtm-to-has_many-through

Resources