Search code examples
ruby-on-railsassociations

Custom Association in ruby on rails


I am finding it hard to understand some of the association defined in the code base.

class Patient < ApplicationRecord   
    belongs_to :g_district, class_name: "District", primary_key: "id", foreign_key: 'district_id', optional: true
    belongs_to :g_perm_district, class_name: "District", primary_key: "id", foreign_key: 'permanent_district_id', optional: true
    belongs_to :g_workplc_district, class_name: "District", primary_key: "id", foreign_key: 'workplace_district_id', optional: true    
end
class District
    belongs_to :province #, optional: true
    belongs_to :division, optional: true
    has_many :hospitals
    has_many :tehsils
    has_many :ucs
    has_many :mobile_users
    has_many :labs
    has_many :insecticides
end

I am not clearly getting these kind of associations defined her.(belongs_to :g_district, class_name: "District", primary_key: "id", foreign_key: 'district_id', optional: true).

In my code, there are no models like g_district, g_perm_district, g_workplc_district.


Solution

  • Your code is associating the same model under different names. When in doubt you can always check this by looking at class_name: "District" which is referencing the actual class name.

    In your case a Patient can have an association with three different districts (but all of them point to the District model):

    3.times { District.create }
    patient = Patient.create(
      g_district: District.find(1), 
      g_perm_district: District.find(2),
      g_workplc_district: District.find(3)
    )
    
    patient.g_district #=> #<District:0x00000001083ce048 id: 1,.. >
    patient.g_perm_district #=> #<District:0x00000001083ce048 id: 2,.. >
    patient.g_workplc_district #=> #<District:0x00000001083ce048 id: 3,.. >
    

    It might also be worth checking the migrations or schema for Patient. The schema table might look like this:

    create_table "patients", force: :cascade do |t|
        t.integer "district_id"
        t.integer "permanent_district_id"
        t.integer "workplace_district_id"
        (...other columns here...)
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
    end
    

    and the migration:

    class CreatePatients < ActiveRecord::Migration[7.0]
      def change
        create_table :patients do |t|
          t.integer :district_id
          t.integer :permanent_district_id
          t.integer :workplace_district_id
          (...other columns here...)
    
          t.timestamps
        end
      end
    end
    

    The foreign_key: 'district_id' part (as well as the other two) suggests that these columns must exist and helps ActiveRecord properly associate the same model multiple times