solnic / virtus

[DISCONTINUED ] Attributes on Steroids for Plain Old Ruby Objects
MIT License
3.77k stars 229 forks source link

How to get attribute default when initialized with nil #172

Closed rawsyntax closed 11 years ago

rawsyntax commented 11 years ago

Given the following example:

class Example
  include Virtus
  attribute :foo, Boolean, default: false 
end

Example.new(foo: nil).foo # => nil

Is there an accepted way to have foo be false here?

We have looked at approaches such as using a reader_class or writer_class, but having the default kick in for attributes set to nil seems reasonable for my use case (given the default value for a Hash key is nil).

Looking at the implementation here starting with the initializer and into where default values are set, we don't see a check for the value of the attribute, just whether or not the instance variable exists.

dkubb commented 11 years ago

I think virtus' semantics are originally based on what we did in DataMapper 1, where if someone does not set a value then we use the default value, but if it's set to anything at all then we honour that. I don't know if you can distinguish between purposeful assignment and assignment where the client expects the default value to be used. There are many valid use cases where someone would explicitly want the value to be nil and for the default value not to overwrite it.

solnic commented 11 years ago

Related: https://github.com/solnic/virtus/issues/154

benlangfeld commented 11 years ago

It seems that this is not just a problem with defaults, but with coercion of nil also:

class Example
  include Virtus
  attribute :foo, Hash
end

# I'd expect this to return {}
Example.new(foo: nil).foo # => nil