1.Single Table inheritance
Add a column called something_type, for example product_type, person_type, animal_type.
Avoid using the name ‘type’, because it is a very old Ruby keyword, and it can cause confusion.
Then define the class method Klass.inheritance_column.
Example:
class Cat < ActiveRecord::Base
has_many :claws, :dependent => :delete_all
def self.inheritance_column
'animal_type'
end
end
create_table :cats do |t|
t.column :age, :integer
t.column :name, :string, :limit => 40, :null => false
t.column :animal_type, :string, :limit => 40;
t.column :cat_attr, :string, :limit => 60
t.column :stripes, :integer
t.timestamp
end
2. Polymorphism
An address can belong to a user or a facility.
class Address < ActiveRecord::Base
belongs_to :owner, polymorphic: true
end
class Facility < ActiveRecord::Base
has_many :addresses, as: :owner
end
class User < ActiveRecord::Base
has_many :addresses, as: :owner
end
class CreateAddresses < ActiveRecord::Migration
def change
create_table :addresses do |t|
t.string :street
t.string :city
t.string :state
t.string :zip
t.string :county_name
t.string :telephone_number
t.references :owner, polymorphic: true, index: true
t.timestamps null: false
end
end
end
3. Associations with different names
A message has users as both sender and recipients.
class Message < ActiveRecord::Base
belongs_to :sender, class_name: 'User', foreign_key: 'sender_id'
has_many :messages_users, dependent: :destroy
has_many :recipients, through: :messages_users
end
class User < ActiveRecord::Base
has_many :sent_messages, class_name: 'Message', foreign_key: 'sender_id'
has_many :messages_users
has_many :received_messages, through: :messages_users
end
class MessagesUser < ActiveRecord::Base
belongs_to :received_message, class_name: 'Message', foreign_key: 'message_id'
belongs_to :recipient, class_name: 'User', foreign_key: 'user_id'
end
class CreateMessages < ActiveRecord::Migration
def change
create_table :messages do |t|
t.string :subject
t.text :content
t.references :sender
t.timestamps null: false
end
end
end
class CreateMessagesUsers < ActiveRecord::Migration
def change
create_table :messages_users do |t|
t.references :message
t.references :user
t.boolean :read_status, default: false
t.timestamps null: false
end
end
end
4. Create index and foreign key constraints in migration code
def create_office_addresses_physicians
create_table :office_addresses_physicians do |t|
t.references :office_address, index: true, foreign_key: true
t.references :physician, index: true, foreign_key: true
t.timestamps null: false
end
end
5. Use foreign key constraints to a table with different name, different foreign key convention
A post refers to an author in table users, foreign_key is author_id
def change
create_table :posts do |t|
t.references :author, index: true
end
add_foreign_key :posts, :users, column: :author_id
end
6. Overriding the Naming Conventions
ApplicationRecord is Rails5’s new base class. Do not use ActiveRecord::Base.
class Product < ApplicationRecord
self.table_name = "my_products"
end
class ProductTest < ActiveSupport::TestCase
set_fixture_class my_products: Product
fixtures :my_products
...
end
class Product < ApplicationRecord
self.primary_key = "product_id"
end