Search code examples
ruby-on-railsrubypostgresqlshopifyshopify-app

Rails how to create relationships between models


I'm developing a Shopify App and I'm trying to create a relationship in my database where I have a Shop model and an Address model, and one shop can have different addresses and every address is related to one shop.

So I have this:

models/shop.rb

class Shop < ActiveRecord::Base
  include ShopifyApp::SessionStorage
  has_many :addresses
end

models/address.rb

class Address < ApplicationRecord
    belongs_to :shop
end

db/migrate/create_shops.rb

class CreateShops < ActiveRecord::Migration[5.1]
    has_many :addresses
  def self.up
    create_table :shops  do |t|
      t.string :shopify_domain, null: false
      t.string :shopify_token, null: false
      t.timestamps
    end

    add_index :shops, :shopify_domain, unique: true
  end

  def self.down
    drop_table :shops
  end
end

db/migrate/create_shops.rb

class CreateAddresses < ActiveRecord::Migration[5.1]
  def change
    create_table :addresses do |t|
      t.text :Address1
      t.text :Address2
      t.string :Postal
      t.string :Phone
      t.string :City

      t.timestamps
    end
  end
end

I think I don't have this well... So, how can I add addresses to a shop in my database?

Thank you.


Solution

  • I think here:

    class CreateShops < ActiveRecord::Migration[5.1]
      has_many :addresses
      def self.up
        create_table :shops  do |t|
          t.string :shopify_domain, null: false
          t.string :shopify_token, null: false
          t.timestamps
        end
    
        add_index :shops, :shopify_domain, unique: true
      end
    
      def self.down
        drop_table :shops
      end
    end
    

    you do not want has_many :addresses. And this:

    class CreateAddresses < ActiveRecord::Migration[5.1]
      def change
        create_table :addresses do |t|
          t.text :Address1
          t.text :Address2
          t.string :Postal
          t.string :Phone
          t.string :City
    
          t.timestamps
        end
      end
    end
    

    should be like this:

    class CreateAddresses < ActiveRecord::Migration[5.1]
      def change
        create_table    :addresses do |t|
          t.references  :shop
          t.string      :address_1
          t.string      :address_2
          t.string      :postal
          t.string      :phone
          t.string      :city
    
          t.timestamps
        end
      end
    end
    

    As mentioned by @engineersmnky in the comments, as of Rails 5, an index is automatically created on the foreign key.

    For future readers who may not be on Rails 5 (or later, depending on how far into the future you are) who want to add an index to the foreign key...

    If you're on Rails 4.x, then do:

    class CreateAddresses < ActiveRecord::Migration
      def change
        create_table    :addresses do |t|
          t.references  :shop, index: true
          t.string      :address_1
          t.string      :address_2
          t.string      :postal
          t.string      :phone
          t.string      :city
    
          t.timestamps
        end
      end
    end
    

    If you're earlier than Rails 4.x, then see this question and answer.