Search code examples
ruby-on-railsrails-activerecord

Ruby on Rails Getting Foreign Key to work


I feel like this is a simple error that I can not figure out, but I haven't found anything online to help explain what I am doing incorrectly. I have three tables created in my Ruby on Rails application:

Facility
 facility_name - string
 address       - string
 city_id       - integer
 state_id      - integer
 
 and foreign keys: cities, states

City
  city_name    - integer
  state_id     - integer

State
  state_short  - string
  state_long   - string

and I have the models defined as:

class Facility < ApplicationRecord
  has_one :city
  has_one :state
end


class City < ApplicationRecord
  belongs_to :state
  belongs_to :facility
end

class State < ApplicationRecord
  has_many :cities
  belongs_to :facility
end

I thought I would be able to bring up the city and state within the facility by the following code on the rails console:

x = Facility.first
x.city_name
x.state_long

but both of those codes give an error. Am I mistaking that by having the city_id and the state_id in the facilities table and the relationships as above, I should be able to get the city_name and state_long from the respective tables?


Solution

  • class Facility < ApplicationRecord
      has_one :city
      has_one :state
    end
    

    It means cities and states tables have facility_id column

    But in your schema facilties have city_id and state_id

    It means you need change your associations this way

    class Facility < ApplicationRecord
      belongs_to :city
      belongs_to :state
    end
    
    class City < ApplicationRecord
      belongs_to :state
      has_one :facility
    end
    
    class State < ApplicationRecord
      has_many :cities
      has_one :facility
    end
    

    Another option is to change schema (if keep associations)

    facilities
    -----------
    facility_name
    address
    
    cities
    -----------
    city_name
    state_id 
    facility_id
    
    states
    -----------
    state_short
    state_long
    facility_id
    

    Other words you need choose between belongs_to and has_one

    The distinction is in where you place the foreign key (it goes on the table for the class declaring the belongs_to association), but you should give some thought to the actual meaning of the data as well. The has_one relationship says that one of something is yours - that is, that something points back to you

    In any case if instance of facility hasn't city_name and state_long methods error will occurred because adding associations doesn't define methods of associated model(s)

    You can call it like this

    facility = Facility.first
    facility.city.city_name
    facility.state.state_long
    

    But can add such methods

    class Facility < ApplicationRecord
      belongs_to :city
      belongs_to :state
    
      def city_name
        city.city_name
      end
    
      def state_long
        state.state_long
      end
    end
    

    or using delegate method

    class Facility < ApplicationRecord
      belongs_to :city
      belongs_to :state
    
      delegate :city_name, to: :city
      delegate :state_long, to: :state
    end
    

    After that you can call it like this

    facility = Facility.first
    facility.city_name
    facility.state_long