12/08/2018, 17:31

Single Table Inheritance with Rails

1 What is Single Table Inheritance (STI)? STI về cơ bản là ý tưởng sử dụng một bảng duy nhất để phản ánh nhiều mô hình kế thừa từ một base model, mà chính nó kế thừa từ ActiveRecord :: Base. Trong lược đồ cơ sở dữ liệu, các mô hình con được chỉ ra bởi một cột "loại" duy nhất. Trong Rails, thêm ...

1 What is Single Table Inheritance (STI)?

STI về cơ bản là ý tưởng sử dụng một bảng duy nhất để phản ánh nhiều mô hình kế thừa từ một base model, mà chính nó kế thừa từ ActiveRecord :: Base. Trong lược đồ cơ sở dữ liệu, các mô hình con được chỉ ra bởi một cột "loại" duy nhất. Trong Rails, thêm một cột "type" trong việc di chuyển cơ sở dữ liệu là đủ (sau khi viết các mô hình) để cho Rails biết rằng bạn đang lên kế hoạch thực hiện STI.

2 Cài đặt:

Tạo 1 project mới:

rails new sti --no-test-framework

Tạo model Tribe:

rails g model tribe name:string

Tạo model Animal:

rails g model animal name:string age:integer race:string

Cột race sẽ được sử dụng bởi Active Record để lưu tên mẫu. Mặc định, AR sẽ tìm kiếm một cột type nhưng bạn có thể sử dụng bất cứ điều gì miễn là bạn nói với AR về nó.

Sau đó, thêm trile_id vào bảng Animal

class AddTribeIdToAnimal < ActiveRecord::Migration
  def change
    add_column :animals, :tribe_id, :integer
  end
end

Và chạy lên migration rake db:migrate

#app/models/tribe.rb

class Tribe < ActiveRecord::Base 
    has_many :animals 
end

#app/models/animal.rb

class Animal < ActiveRecord::Base 
    belongs_to :tribe 
    self.inheritance_column = :race 

    # We will need a way to know which animals
    # will subclass the Animal model
    def self.races
      %w(Lion WildBoar Meerkat)
    end

end

#app/models/lion.rb

class Lion < Animal
end 

#app/models/meerkat.rb

class Meerkat < Animal;
end 

#app/models/wildBoar.rb

class WildBoar < Animal
end

self.inheritance_column = :race được sử dụng để chị đình trường STI và không cần thiết nếu như chúng ta sử dụng trường mặc định là type.

#app/models/animal.rb

scope :lions, -> {where(race: “Lion”)}

scope :meerkats, -> {where(race: “Meerkat”)}

scope :wild_boars, -> {where(race: “WildBoar”)}

Thêm delegate vào model Tribe

delegate :lions, :meerkats, :wild_boars, to: :animals

Tạo dữ liệu để kiểm tra:

tribe = Tribe.create(name: 'LionTribe')

tribe.animals << Lion.new(name: "Simba", age: 10) 
tribe.animals << WildBoar.new(name: "Pumba", age: 30) 
tribe.animals << Meerkat.new(name: "Timon", age: 30)
0