For one-to-one relationships, You can use the has_one and belongs_to in your models.
Note: one-to-one relationship does not support through associations yet.
classTeam < Granite::Base has_one :coach column id :Int64, primary: true column name :Stringend
This will add a coach and coach= instance methods to the team which returns associated coach.
classCoach < Granite::Base table coaches belongs_to :team column id :Int64, primary: true column name :Stringend
This will add a team and team= instance method to the coach.
For example:
team =Team.find! 1# has_one side..puts team.coachcoach =Coach.find! 1# belongs_to side...puts coach.teamcoach.team = teamcoach.save# or in one-to-one you can also doteam.coach = coach# coach is the child entity and contians the foreign_key# so save should called on coach instancecoach.save
In this example, you will need to add a team_id and index to your coaches table:
Foreign key is inferred from the class name of the Model which uses has_one. In above case team_id is assumed to be present in coaches table. In case its different you can specify one like this:
classTeam < Granite::Base has_one :coach, foreign_key: :custom_id column id :Int64, primary: true column name :StringendclassCoach < Granite::Base belongs_to :team column id :Int64, primary: trueend
The class name inferred from the name but you can specify the class name:
classTeam < Granite::Base has_one coach :Coach, foreign_key: :custom_id # or you can provide the class name as a parameter has_one :coach, class_name: Coach, foreign_key: :custom_id column id :Int64, primary: true column name :StringendclassCoach < Granite::Base belongs_to team :Team # provide a custom foreign key belongs_to team :Team, foreign_key: team_uuid :String column id :Int64, primary: trueend
One to Many
belongs_to and has_many macros provide a rails like mapping between Objects.
classUser < Granite::Base connection mysql has_many :post # pluralization requires providing the class name has_many posts :Post # or you can provide class name as a parameter has_many :posts, class_name: Post # you can provide a custom foreign key has_many :posts, class_name: Post, foreign_key: :custom_id column id :Int64, primary: true column name :String column email :String timestampsend
This will add a posts instance method to the user which returns an array of posts.
classPost < Granite::Base connection mysql table posts belongs_to :user # or custom name belongs_to my_user :User # or custom foreign key belongs_to user :User, foreign_key: uuid :String column id :Int64, primary: true column title :String timestampsend
This will add a user and user= instance method to the post.
For example:
user =User.find! 1user.posts.each do |post|puts post.titleendpost =Post.find! 1puts post.userpost.user = userpost.save
In this example, you will need to add a user_id and index to your posts table:
CREATETABLEposts ( id BIGSERIALPRIMARY KEY, user_id BIGINT, title VARCHAR, created_at TIMESTAMP, updated_at TIMESTAMP);CREATEINDEXuser_id_idxON posts (user_id);
Many to Many
Instead of using a hidden many-to-many table, Granite recommends always creating a model for your join tables. For example, let's say you have many users that belong to many rooms. We recommend adding a new model called participants to represent the many-to-many relationship.
Then you can use the belongs_to and has_many relationships going both ways.
classUser < Granite::Base has_many :participants, class_name: Participant column id :Int64, primary: true column name :StringendclassParticipant < Granite::Base table participants belongs_to :user belongs_to :room column id :Int64, primary: trueendclassRoom < Granite::Base table rooms has_many :participants, class_name: Participant column id :Int64, primary: true column name :Stringend
The Participant class represents the many-to-many relationship between the Users and Rooms.