5

我有一个数据对象,其中包含用于各种输入的数十个 attr_accessor 字段。我可以以某种方式定义类,以便所有字段的所有设置器将例如将值设置为空字符串而不是尝试的 nil?

4

2 回答 2

9

这是一个小模块:

module NilToBlankAttrAccessor

  def nil_to_blank_attr_accessor(attr)
    attr_reader attr
    define_method "#{attr}=" do |value|
      value = '' if value.nil?
      instance_variable_set "@#{attr}", value
    end
  end

end

只需将其混合:

class Foo
  extend NilToBlankAttrAccessor
  nil_to_blank_attr_accessor :bar
end

并使用它:

foo = Foo.new
foo.bar = nil
p foo.bar        # => ""
foo.bar = 'abc'
p foo.bar        # => "abc"

这个怎么运作

NilToBlankAttrAccessor#nil_to_blank_attr_accessor首先通常定义attr_reader:

    attr_reader attr

然后它通过定义一个与访问器同名的方法来定义编写器,只是在末尾带有一个“=”。所以,对于属性:bar,方法被命名为bar=

    define_method "#{attr}=" do |value|
      ...
    end

现在它需要设置变量。首先它将 nil 变成一个空字符串:

      value = '' if value.nil?

然后使用 instance_variable_set,它执行实例变量赋值,其中实例变量在运行时才知道。

      instance_variable_set "@#{attr}", value

Foo 类需要 nil_to_blank_attr_accessor 是类方法,而不是实例方法,因此它使用extend而不是include

class Foo
  extend NilToBlankAttrAccessor
  ...
end
于 2013-03-16T16:26:13.303 回答
1

而不是做

object.foo = given_input

你应该做

object.foo = given_input.nil? ? "" : given_input

或者如果你也想变成false""那么

object.foo = given_input || ""
于 2013-03-16T16:25:43.187 回答