跳至內容 跳至搜尋
方法
C
I
L
N
P
Q
R
S
T

實例公開方法

column_defaults()

返回一個雜湊,其中鍵是欄位名稱,值是在為此表格實例化 Active Record 物件時的預設值。

# File activerecord/lib/active_record/model_schema.rb, line 472
def column_defaults
  load_schema
  @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
end

column_for_attribute(name)

返回指定屬性的欄位物件。如果指定的屬性不存在,則返回 ActiveRecord::ConnectionAdapters::NullColumn。

class Person < ActiveRecord::Base
end

person = Person.new
person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
# => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>

person.column_for_attribute(:nothing)
# => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
# File activerecord/lib/active_record/model_schema.rb, line 463
def column_for_attribute(name)
  name = name.to_s
  columns_hash.fetch(name) do
    ConnectionAdapters::NullColumn.new(name)
  end
end

column_names()

返回一個包含欄位名稱的字串陣列。

# File activerecord/lib/active_record/model_schema.rb, line 478
def column_names
  @column_names ||= columns.map(&:name).freeze
end

columns()

# File activerecord/lib/active_record/model_schema.rb, line 432
def columns
  @columns ||= columns_hash.values.freeze
end

content_columns()

返回一個欄位物件陣列,其中已移除主鍵 ID、所有以「_id」或「_count」結尾的欄位,以及用於單表繼承的欄位。

# File activerecord/lib/active_record/model_schema.rb, line 489
def content_columns
  @content_columns ||= columns.reject do |c|
    c.name == primary_key ||
    c.name == inheritance_column ||
    c.name.end_with?("_id", "_count")
  end.freeze
end

ignored_columns()

模型應忽略的欄位名稱列表。被忽略的欄位將不會定義屬性存取器,也不會在 SQL 查詢中被引用。

# File activerecord/lib/active_record/model_schema.rb, line 331
def ignored_columns
  @ignored_columns || superclass.ignored_columns
end

ignored_columns=(columns)

設定模型應忽略的欄位名稱。被忽略的欄位將不會定義屬性存取器,也不會在 SQL 查詢中被引用。

此方法的常見用法是在部署和執行從資料庫中刪除欄位的遷移之前,確保已移除和部署對屬性的所有引用。使用這種兩步驟方法刪除欄位可確保在執行架構遷移時,沒有程式碼會因為記憶體中存在快取的架構而引發錯誤。

例如,假設您要刪除模型中的「category」屬性,首先將其標記為已忽略

class Project < ActiveRecord::Base
  # schema:
  #   id         :bigint
  #   name       :string, limit: 255
  #   category   :string, limit: 255

  self.ignored_columns += [:category]
end

架構仍然包含「category」,但現在模型會忽略它,因此任何元數據驅動的程式碼或架構快取都不會嘗試使用該欄位

Project.columns_hash["category"] => nil

如果您直接存取該屬性,將會收到錯誤訊息,因此請確保已移除該欄位的所有用法(自動化測試可以幫助您找到任何用法)。

user = Project.create!(name: "First Project")
user.category # => raises NoMethodError
# File activerecord/lib/active_record/model_schema.rb, line 366
def ignored_columns=(columns)
  reload_schema_from_cache
  @ignored_columns = columns.map(&:to_s).freeze
end

load_schema()

從架構快取或直接從資料庫載入模型的架構資訊。

# File activerecord/lib/active_record/model_schema.rb, line 534
def load_schema
  return if schema_loaded?
  @load_schema_monitor.synchronize do
    return if schema_loaded?

    load_schema!

    @schema_loaded = true
  rescue
    reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
    raise
  end
end

next_sequence_value()

傳回插入語句中將用作主鍵的下一個值。

# File activerecord/lib/active_record/model_schema.rb, line 411
def next_sequence_value
  with_connection { |c| c.next_sequence_value(sequence_name) }
end

prefetch_primary_key?()

判斷是否應在插入語句之前從其相應的序列中選擇主鍵值。

# File activerecord/lib/active_record/model_schema.rb, line 405
def prefetch_primary_key?
  with_connection { |c| c.prefetch_primary_key?(table_name) }
end

protected_environments()

應禁止破壞性動作的環境名稱陣列。預設情況下,值為 `["production"]`。

# File activerecord/lib/active_record/model_schema.rb, line 312
def protected_environments
  if defined?(@protected_environments)
    @protected_environments
  else
    superclass.protected_environments
  end
end

protected_environments=(environments)

設定應禁止破壞性動作的環境名稱陣列。

# File activerecord/lib/active_record/model_schema.rb, line 321
def protected_environments=(environments)
  @protected_environments = environments.map(&:to_s)
end

quoted_table_name()

返回表格名稱的引號版本。

# File activerecord/lib/active_record/model_schema.rb, line 285
def quoted_table_name
  adapter_class.quote_table_name(table_name)
end

reset_column_information()

重設關於欄位的所有快取資訊,這將導致在下一個請求時重新載入它們。

此方法最常見的用法可能是在遷移中,例如在建立表格後,您想要用一些預設值填充它,例如

class CreateJobLevels < ActiveRecord::Migration[8.0]
  def up
    create_table :job_levels do |t|
      t.integer :id
      t.string :name

      t.timestamps
    end

    JobLevel.reset_column_information
    %w{assistant executive manager director}.each do |type|
      JobLevel.create(name: type)
    end
  end

  def down
    drop_table :job_levels
  end
end
# File activerecord/lib/active_record/model_schema.rb, line 523
def reset_column_information
  connection_pool.active_connection&.clear_cache!
  ([self] + descendants).each(&:undefine_attribute_methods)
  schema_cache.clear_data_source_cache!(table_name)

  reload_schema_from_cache
  initialize_find_by_cache
end

sequence_name()

# File activerecord/lib/active_record/model_schema.rb, line 371
def sequence_name
  if base_class?
    @sequence_name ||= reset_sequence_name
  else
    (@sequence_name ||= nil) || base_class.sequence_name
  end
end

sequence_name=(value)

將產生 ID 時使用的序列名稱設定為給定值,或者(如果值為 `nil` 或 `false`)設定為給定區塊返回的值。這對於 Oracle 是必需的,並且對於任何依賴序列產生主鍵的資料庫都很有用。

如果在使用 Oracle 時未明確設定序列名稱,則預設情況下將使用常用的模式:#{table_name}_seq

如果在使用 PostgreSQL 時未明確設定序列名稱,它將會自動找出與您的主鍵相對應的序列。

class Project < ActiveRecord::Base
  self.sequence_name = "projectseq"   # default would have been "project_seq"
end
# File activerecord/lib/active_record/model_schema.rb, line 398
def sequence_name=(value)
  @sequence_name          = value.to_s
  @explicit_sequence_name = true
end

table_exists?()

指示與此類別關聯的表格是否存在

# File activerecord/lib/active_record/model_schema.rb, line 416
def table_exists?
  schema_cache.data_source_exists?(table_name)
end

table_name()

根據直接繼承自 `ActiveRecord::Base` 的繼承階層架構中類別的名稱,猜測表格名稱(強制使用小寫)。因此,如果階層架構如下所示:Reply < Message < `ActiveRecord::Base`,則即使在 Reply 上呼叫,也會使用 Message 來猜測表格名稱。用於進行猜測的規則由 Active Support 中的 Inflector 類別處理,該類別幾乎知道所有常見的英文變形。您可以在 config/initializers/inflections.rb 中新增新的變形。

巢狀類別的表格名稱會加上父類別表格名稱的單數形式作為前綴。不考慮封閉模組。

範例

class Invoice < ActiveRecord::Base
end

file                  class               table_name
invoice.rb            Invoice             invoices

class Invoice < ActiveRecord::Base
  class Lineitem < ActiveRecord::Base
  end
end

file                  class               table_name
invoice.rb            Invoice::Lineitem   invoice_lineitems

module Invoice
  class Lineitem < ActiveRecord::Base
  end
end

file                  class               table_name
invoice/lineitem.rb   Invoice::Lineitem   lineitems

此外,還會在前面加上類別層級的 `table_name_prefix`,並在後面加上 `table_name_suffix`。因此,如果您有一個前綴「myapp_」,則 Invoice 類別的表格名稱猜測將變為「myapp_invoices」。Invoice::Lineitem 將變為「myapp_invoice_lineitems」。

Active Model Naming 的 `model_name` 是用於猜測表格名稱的基本名稱。如果定義了自訂 Active Model Name,它也將用於表格名稱

class PostRecord < ActiveRecord::Base
  class << self
    def model_name
      ActiveModel::Name.new(self, nil, "Post")
    end
  end
end

PostRecord.table_name
# => "posts"

您也可以明確地設定自己的表格名稱

class Mouse < ActiveRecord::Base
  self.table_name = "mice"
end
# File activerecord/lib/active_record/model_schema.rb, line 260
def table_name
  reset_table_name unless defined?(@table_name)
  @table_name
end

table_name=(value)

明確設定表格名稱。範例

class Project < ActiveRecord::Base
  self.table_name = "project"
end
# File activerecord/lib/active_record/model_schema.rb, line 270
def table_name=(value)
  value = value && value.to_s

  if defined?(@table_name)
    return if value == @table_name
    reset_column_information if connected?
  end

  @table_name        = value
  @arel_table        = nil
  @sequence_name     = nil unless @explicit_sequence_name
  @predicate_builder = nil
end

實例保護方法

initialize_load_schema_monitor()

# File activerecord/lib/active_record/model_schema.rb, line 549
def initialize_load_schema_monitor
  @load_schema_monitor = Monitor.new
end

reload_schema_from_cache(recursive = true)

# File activerecord/lib/active_record/model_schema.rb, line 553
def reload_schema_from_cache(recursive = true)
  @_returning_columns_for_insert = nil
  @arel_table = nil
  @column_names = nil
  @symbol_column_to_string_name_hash = nil
  @content_columns = nil
  @column_defaults = nil
  @attributes_builder = nil
  @columns = nil
  @columns_hash = nil
  @schema_loaded = false
  @attribute_names = nil
  @yaml_encoder = nil
  if recursive
    subclasses.each do |descendant|
      descendant.send(:reload_schema_from_cache)
    end
  end
end