跳至内容 跳至搜索

Active Model – Rails 的模型接口

Active Model 提供了一组标准接口供模型类使用。例如,它们允许 Action Pack 辅助方法与非 ActiveRecord 模型进行交互。Active Model 也有助于构建自定义 ORM,以便在 Rails 框架之外使用。

您可以在 Active Model Basics 指南中阅读更多关于 Active Model 的信息。

在 Rails 3.0 之前,如果插件或 gem 开发者想让一个对象与 Action Pack 辅助方法交互,他们需要从 Rails 复制代码片段,或者 monkey patch 整个辅助方法来让它们处理不完全符合 ActiveRecord 接口的对象。这会导致代码重复和应用程序脆弱,升级时容易出错。Active Model 通过定义一个显式的 API 来解决这个问题。您可以在 ActiveModel::Lint::Tests 中阅读更多关于 API 的信息。

Active Model 提供了一个默认模块,该模块实现了与 Action Pack 开箱即用集成所需的基本 APIActiveModel::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
    

    了解更多

  • 针对特定操作的 Callbacks

    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

源代码可以作为 Rails 项目的一部分在 GitHub 上下载。

许可证

Active Model 在 MIT 许可证下发布

支持

API 文档位于:

Ruby on Rails 项目的错误报告可在此处提交:

功能请求应在此处的 rubyonrails-core 论坛上讨论:

命名空间
方法
E
G
V

类公共方法

eager_load!()

# File activemodel/lib/active_model.rb, line 82
def self.eager_load!
  super
  ActiveModel::Serializers.eager_load!
end

gem_version()

返回 Active Model 当前加载的版本,格式为 Gem::Version

# File activemodel/lib/active_model/gem_version.rb, line 5
def self.gem_version
  Gem::Version.new VERSION::STRING
end

version()

返回 Active Model 当前加载的版本,格式为 Gem::Version

# File activemodel/lib/active_model/version.rb, line 7
def self.version
  gem_version
end