跳到內容 跳到搜尋

Active Model – Rails 的模型介面

Active Model 提供一套已知的介面,供模型類別使用。它們允許 Action Pack 輔助程式與非 Active Record 模型互動,例如 Active Model 也協助建置自訂的 ORM,以供 Rails 架構之外使用。

您可以在 Active Model 基本概念 指南中,進一步了解 Active Model。

在 Rails 3.0 之前,如果外掛程式或動態套件的開發者想要讓物件與 Action Pack 輔助程式互動,則必須複製 Rails 中的程式碼區塊,或修改完整的輔助程式,以處理與 Active Record 介面並不完全相符的物件。這將導致程式碼重複,而且應用程式在升級時會容易損壞。Active Model 透過定義一個明確的 API 來解決此問題。您可以在 ActiveModel::Lint::Tests 了解有關 API 的更多資訊。

Active Model 提供一個預設模組,以實作基本 API,以便直接與 Action Pack 整合:ActiveModel::API

class Person
  include ActiveModel::API

  attr_accessor :name, :age
  validates_presence_of :name
end

person = Person.new(name: 'bob', age: '18')
person.name   # => 'bob'
person.age    # => '18'
person.valid? # => true

它包含模型名稱內省、轉換、翻譯和驗證,產生一個適合用於 Action Pack 的類別。請參閱 ActiveModel::API,以取得更多範例。

Active Model 還提供以下功能,以在開箱即用時具備類 ORM 的行為

  • 為物件加入屬性魔法

    class Person
      include ActiveModel::AttributeMethods
    
      attribute_method_prefix 'clear_'
      define_attribute_methods :name, :age
    
      attr_accessor :name, :age
    
      def clear_attribute(attr)
        send("#{attr}=", nil)
      end
    end
    
    person = Person.new
    person.clear_name
    person.clear_age
    

    取得了解

  • 特定操作的呼叫回函

    class Person
      extend ActiveModel::Callbacks
      define_model_callbacks :create
    
      def create
        run_callbacks :create do
          # Your create action methods here
        end
      end
    end
    

    這會產生 before_createaround_createafter_create 類別方法,以包裹您的 create 方法。

    取得了解

  • 追蹤值變更

    class Person
      include ActiveModel::Dirty
    
      define_attribute_methods :name
    
      def name
        @name
      end
    
      def name=(val)
        name_will_change! unless val == @name
        @name = val
      end
    
      def save
        # do persistence work
        changes_applied
      end
    end
    
    person = Person.new
    person.name             # => nil
    person.changed?         # => false
    person.name = 'bob'
    person.changed?         # => true
    person.changed          # => ['name']
    person.changes          # => { 'name' => [nil, 'bob'] }
    person.save
    person.name = 'robert'
    person.save
    person.previous_changes # => {'name' => ['bob, 'robert']}
    

    取得了解

  • 為物件加入 errors 介面

    揭露錯誤訊息,讓物件可以與 Action Pack 輔助程式互動,而不會產生無縫。

    class Person
    
      def initialize
        @errors = ActiveModel::Errors.new(self)
      end
    
      attr_accessor :name
      attr_reader   :errors
    
      def validate!
        errors.add(:name, "cannot be nil") if name.nil?
      end
    
      def self.human_attribute_name(attr, options = {})
        "Name"
      end
    end
    
    person = Person.new
    person.name = nil
    person.validate!
    person.errors.full_messages
    # => ["Name cannot be nil"]
    

    取得了解

  • 模型名稱內省

    class NamedPerson
      extend ActiveModel::Naming
    end
    
    NamedPerson.model_name.name   # => "NamedPerson"
    NamedPerson.model_name.human  # => "Named person"
    

    取得了解

  • 讓物件可序列化

    ActiveModel::Serialization 為您的物件提供一個標準介面,以提供 to_json 序列化。

    class SerialPerson
      include ActiveModel::Serialization
    
      attr_accessor :name
    
      def attributes
        {'name' => name}
      end
    end
    
    s = SerialPerson.new
    s.serializable_hash   # => {"name"=>nil}
    
    class SerialPerson
      include ActiveModel::Serializers::JSON
    end
    
    s = SerialPerson.new
    s.to_json             # => "{\"name\":null}"
    

    取得了解

  • 國際化 (i18n) 支援

    class Person
      extend ActiveModel::Translation
    end
    
    Person.human_attribute_name('my_attribute')
    # => "My attribute"
    

    取得了解

  • 驗證支援

    class Person
      include ActiveModel::Validations
    
      attr_accessor :first_name, :last_name
    
      validates_each :first_name, :last_name do |record, attr, value|
        record.errors.add attr, "starts with z." if value.start_with?("z")
      end
    end
    
    person = Person.new
    person.first_name = 'zoolander'
    person.valid?  # => false
    

    取得了解

  • 自訂驗證器

    class HasNameValidator < ActiveModel::Validator
      def validate(record)
        record.errors.add(:name, "must exist") if record.name.blank?
      end
    end
    
    class ValidatorPerson
      include ActiveModel::Validations
      validates_with HasNameValidator
      attr_accessor :name
    end
    
    p = ValidatorPerson.new
    p.valid?                  # =>  false
    p.errors.full_messages    # => ["Name must exist"]
    p.name = "Bob"
    p.valid?                  # =>  true
    

    取得了解

下載及安裝

可以使用 RubyGems 安裝最新版本的 Active Model

$ gem install activemodel

可以從 GitHub 上的 Rails 專案下載原始碼

授權

Active Model 是根據 MIT 授權發布的

支援

API 文件位於

Ruby on Rails 專案的錯誤報告可以在此處提交

功能要求應在 rails-core 郵寄清單上討論