跳至內容 跳至搜尋
方法
A
B
C
D
N
P
S

屬性

[RW] abstract_class

如果這是抽象類別(請參閱abstract_class?),請將其設定為true。如果您使用繼承搭配 Active Record,並不想讓類別被視為 STI 層級的一部分,則必須將其設定為 true。例如,ApplicationRecord 會產生為一個抽象類別。

考量下列預設行為

Shape = Class.new(ActiveRecord::Base)
Polygon = Class.new(Shape)
Square = Class.new(Polygon)

Shape.table_name   # => "shapes"
Polygon.table_name # => "shapes"
Square.table_name  # => "shapes"
Shape.create!      # => #<Shape id: 1, type: nil>
Polygon.create!    # => #<Polygon id: 2, type: "Polygon">
Square.create!     # => #<Square id: 3, type: "Square">

不過,使用 abstract_class 時,Shape 會從層級中省略。

class Shape < ActiveRecord::Base
  self.abstract_class = true
end
Polygon = Class.new(Shape)
Square = Class.new(Polygon)

Shape.table_name   # => nil
Polygon.table_name # => "polygons"
Square.table_name  # => "polygons"
Shape.create!      # => NotImplementedError: Shape is an abstract class and cannot be instantiated.
Polygon.create!    # => #<Polygon id: 1, type: nil>
Square.create!     # => #<Square id: 2, type: "Square">

請注意,在上述範例中,為了禁止建立純粹的Polygon,您應該使用validates :type, presence: true,而不是將其設定為抽象類別。透過這個方式,Polygon 會保留在層級中,而 Active Record 會繼續正確地推導資料表名稱。

[R] base_class

傳回繼承層級的第一個類別,其繼承自抽象類別或ActiveRecord::Base

考量下列行為

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end
class Shape < ApplicationRecord
  self.abstract_class = true
end
Polygon = Class.new(Shape)
Square = Class.new(Polygon)

ApplicationRecord.base_class # => ApplicationRecord
Shape.base_class # => Shape
Polygon.base_class # => Polygon
Square.base_class # => Polygon

執行個體公開的方法

abstract_class?()

傳回此類別是否為抽象類別。

# File activerecord/lib/active_record/inheritance.rb, line 167
def abstract_class?
  @abstract_class == true
end

base_class?()

傳回類別是否為基礎類別。有關更多資訊,請參閱base_class

# File activerecord/lib/active_record/inheritance.rb, line 119
def base_class?
  base_class == self
end

descends_from_active_record?()

如果不需要 STI 類型條件,則傳回 true。如果需要套用 STI 類型條件,則傳回 false

# File activerecord/lib/active_record/inheritance.rb, line 82
def descends_from_active_record?
  if self == Base
    false
  elsif superclass.abstract_class?
    superclass.descends_from_active_record?
  else
    superclass == Base || !columns_hash.include?(inheritance_column)
  end
end

new(attributes = nil, &block)

判定傳入的屬性之一是否為繼承欄位,如果繼承欄位可供屬性存取,它會初始化指定子類別的執行個體,而非基礎類別。

# File activerecord/lib/active_record/inheritance.rb, line 56
def new(attributes = nil, &block)
  if abstract_class? || self == Base
    raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
  end

  if _has_attribute?(inheritance_column)
    subclass = subclass_from_attributes(attributes)

    if subclass.nil? && scope_attributes = current_scope&.scope_for_create
      subclass = subclass_from_attributes(scope_attributes)
    end

    if subclass.nil? && base_class?
      subclass = subclass_from_attributes(column_defaults)
    end
  end

  if subclass && subclass != self
    subclass.new(attributes, &block)
  else
    super
  end
end

polymorphic_class_for(name)

傳回提供 name 的類別。

用於找出儲存在多態類型欄位中,與值對應的類別。

# File activerecord/lib/active_record/inheritance.rb, line 218
def polymorphic_class_for(name)
  if store_full_class_name
    name.constantize
  else
    compute_type(name)
  end
end

polymorphic_name()

傳回多態 關聯 的多態類型欄位中,要儲存的值。

# File activerecord/lib/active_record/inheritance.rb, line 211
def polymorphic_name
  store_full_class_name ? base_class.name : base_class.name.demodulize
end

primary_abstract_class()

設定 Active Record 的應用程式記錄類別

如果應用程式使用不同的類別作為主要抽象類別,則這個很有用。此類別將與 Active Record 共用資料庫連線。這個類別將連線至您的主要資料庫。

# File activerecord/lib/active_record/inheritance.rb, line 177
def primary_abstract_class
  if ActiveRecord.application_record_class && ActiveRecord.application_record_class.name != name
    raise ArgumentError, "The `primary_abstract_class` is already set to #{ActiveRecord.application_record_class.inspect}. There can only be one `primary_abstract_class` in an application."
  end

  self.abstract_class = true
  ActiveRecord.application_record_class = self
end

sti_class_for(type_name)

傳回提供 type_name 的類別。

用於找出儲存在繼承欄位中,與值對應的類別。

# File activerecord/lib/active_record/inheritance.rb, line 194
def sti_class_for(type_name)
  if store_full_sti_class && store_full_class_name
    type_name.constantize
  else
    compute_type(type_name)
  end
rescue NameError
  raise SubclassNotFound,
    "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
    "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
    "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
    "or overwrite #{name}.inheritance_column to use another column for that information. " \
    "If you wish to disable single-table inheritance for #{name} set " \
    "#{name}.inheritance_column to nil"
end

sti_name()

傳回 STI 要儲存在繼承欄位中的值。

# File activerecord/lib/active_record/inheritance.rb, line 187
def sti_name
  store_full_sti_class && store_full_class_name ? name : name.demodulize
end

受保護的實體方法

compute_type(type_name)

傳回記錄的類別類型,使用目前模組作為字首。因此,MyApp::Business::Account 的後代會顯示為 MyApp::Business:AccountSubclass。

# File activerecord/lib/active_record/inheritance.rb, line 242
def compute_type(type_name)
  if type_name.start_with?("::")
    # If the type is prefixed with a scope operator then we assume that
    # the type_name is an absolute reference.
    type_name.constantize
  else
    type_candidate = @_type_candidates_cache[type_name]
    if type_candidate && type_constant = type_candidate.safe_constantize
      return type_constant
    end

    # Build a list of candidates to search for
    candidates = []
    name.scan(/::|$/) { candidates.unshift "#{$`}::#{type_name}" }
    candidates << type_name

    candidates.each do |candidate|
      constant = candidate.safe_constantize
      if candidate == constant.to_s
        @_type_candidates_cache[type_name] = candidate
        return constant
      end
    end

    raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
  end
end