attr_checked函数在《ruby元编程》中的实现

以下的是我自己写的版本

module CheckedAttributes
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def attr_checked(attr_name, &validation)
      define_method("#{attr_name}=") do |value|
        result = validation.call value
        if result
          @attr_name = value
        else
          raise "value is not valid"
        end
      end
      attr_reader attr_name.to_sym
    end
  end
end

以下是书中的版本

module CheckedAttributes
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def attr_checked(attribute, &validation)
      define_method("#{attribute}=") do |value|
        raise 'Invalid attribute' unless validation.call(value)
        instance_variable_set("@#{attribute}", value)
      end

      define_method attribute do
        instance_variable_get "@#{attribute}"
      end
    end
  end
end

测试代码


class Person
  include CheckedAttributes

  attr_checked :age do |v|
    v >= 18
  end
end

me = Person.new
p me.age = 39  # OK
p me.age = 39  # OK
p me.age = 12  # not OK