attr_accessor which transforms nil into string on write

ruby

Solution

Here's a little module to do it:

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

Just mix it in:

class Foo
  extend NilToBlankAttrAccessor
  nil_to_blank_attr_accessor :bar
end

And use it:

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

How it works

`NilToBlankAttrAccessor#nil_to_blank_attr_accessor` first defines the attr_reader normally:

    attr_reader attr

Then it defines the writer by defining a method with the same name as the accessor, only with an "=" at the end. So, for attribute `:bar`, the method is named `bar=`

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

Now it needs to set the variable. First it turns nil into an empty string:

      value = '' if value.nil?

Then use instance_variable_set, which does an instance variable assignment where the instance variable isn't known until runtime.

      instance_variable_set "@#{attr}", value

Class Foo needs nil_to_blank_attr_accessor to be a class method, not an instance method, so it uses `extend` instead of `include`:

class Foo
  extend NilToBlankAttrAccessor
  ...
end

Problem

I have a data object that contains dozens of attr_accessor fields for various inputs. Can I somehow define the class so that all setters for all fields will e.g. set the value as an empty string instead of the attempted nil?

Original source