attr_accessor在写入时将nil转换为字符串

时间:2013-03-16 16:06:59

标签: ruby

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

2 个答案:

答案 0 :(得分: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

Class Foo需要nil_to_blank_attr_accessor作为类方法,而不是实例方法,所以它使用extend代替include

class Foo
  extend NilToBlankAttrAccessor
  ...
end

答案 1 :(得分:1)

而不是做

object.foo = given_input

你应该做

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

或者如果您想将false转换为"",那么

object.foo = given_input || ""