Rails Virtus vs ActiveModel 应该选哪个?

ericguo · April 12, 2014 · Last by ericguo replied at April 13, 2014 · 3778 hits

读了重构臃肿 ActiveRecord 模型的 7 种方式这篇相当经典的文章,我注意到了文中提到的Virtus这个 gem,可以相当漂亮的解决一次表单更新多个 model 这样的情况,比如这段摘自文章里面的代码:

class Signup
  include Virtus

  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  attr_reader :user
  attr_reader :company

  attribute :name, String
  attribute :company_name, String
  attribute :email, String

  validates :email, presence: true
  # … more validations …

  # Forms are never themselves persisted
  def persisted?
    false
  end

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

private

  def persist!
    @company = Company.create!(name: company_name)
    @user = @company.users.create!(name: name, email: email)
  end
end

这样用到 SignUp 的 controller 就可以非常的精简:

class SignupsController < ApplicationController
  def create
    @signup = Signup.new(params[:signup])

    if @signup.save
      redirect_to dashboard_path
    else
      render "new"
    end
  end
end

但是我注意到这篇经典文章写于 2012 年,然后 2013 年 Rails 4 引入了ActiveModel::Model,所以似乎第一段代码也可以用 ActiveModel::Model 这样实现:

class Signup
  include ActiveModel::Model

  attr_accessor(
    :company_name,
    :email,
    :name,
  )

  attr_reader :user
  attr_reader :company

  validates :company_name, presence: true
  validates :email, presence: true, email: true
  validates :name, presence: true

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

private
  def persist!
    @company = Company.create!(name: company_name)
    @user = @company.users.create!(name: name, email: email)
  end
end

显然后一种 Signup 的实现更短,而且persisted?方法也在 ActiveModel::Model 里面定义了,还能省不少行数,且不用引入一个额外的 gem,但是这样用真的没有啥其他问题么?

attribute :age, Integer 要的不是字符串呢

2 Floor has deleted
You need to Sign in before reply, if you don't have an account, please Sign up first.