Conversation
sled
commented
Apr 7, 2016
- Default value type wrapper
- Collections should be empty and not nil by default
- Specs
|
Looks okay so far, but I'd not merge collection stuff into the same PR. |
|
oh wow this also directly does empty collections! However there seems to be an issue with one spec. Root cause is that the model's initializer is called with a string, which can't be coerced into hash with Further investigation: https://github.com/at-point/porro/blob/sled-empty-collections/spec/porro/types/object_spec.rb#L14 Is tested against https://github.com/at-point/porro/blob/sled-empty-collections/spec/support/shared_type.rb#L10 Which results in a call like:
|
|
Any chance we can avoid that and add a guard in the initializer / to_h, also when e.g. |
|
|
||
| def initialize(params = {}) | ||
| self.attributes = params | ||
| self.attributes = attributes.merge(params.to_h) |
There was a problem hiding this comment.
something like
params = params.respond_to?(:to_h) ? params.to_h : {}
attributes.merge(params)There was a problem hiding this comment.
and it need specs, also that a load is done on initialize
There was a problem hiding this comment.
nil is not a problem for vanilla ruby nil.to_h => {}, however isn't it an user error if something non-hashy is passed to the model constructor?
There was a problem hiding this comment.
agree that it is a user error - we could add a workaround maybe in the shared specs?
lib/porro/types/email.rb
Outdated
| self | ||
| end | ||
|
|
||
| def self.default(value) |
There was a problem hiding this comment.
glaube da würd ich eher eifach default nöd implementiere, so gsehts eso us als obs implemntiert wär, für das hämmer ja de supports: [] array
|
@lwe can you check the specs? not sure about the What I want to test is: Given a subject of any type with a default value set to:
It should return the default literal if loaded with nil and dump the default literal if dumped with nil. |
| it_behaves_like 'a Type', supports: nil | ||
| subject { described_class.new(%w{male female}).default('female') } | ||
| #it_behaves_like 'a Type', supports: nil | ||
|
|
|
There's a gotcha with the default value, in combination with an enum.
This defaults to 15 although 15 is not "valid" with respect to the enum, however the cycle "Porro -> Dump -> Porro" works fine, keeping the 15. I think this is more a "definition" question how we want to handle this... Keeping it as is or a possible alternative could be to ask the underlying type whether it |
| def load(value) | ||
| @wrapper.load(value) || default_proc.call | ||
| @wrapper.load(value) || @wrapper.load(default_proc.call) | ||
| end |
There was a problem hiding this comment.
this line is a bit controversial...
Doing a short-ciruit here like previously @wrapper.load(value) || default_proc.call allows invalid values to be assigned i.e
attribute :gender, Porro::Types::Enum.new(%w{male female}).default('hybrid')
will lead to Model.new.gender to return 'hybrid' although it's not a valid value for the enum.
The variant @wrapper.load(value || default_proc.call) will fail some tests, i.e
attribute :gender, Porro::Types::Enum.new(%w{male female}).default('female')
it 'converts anything else to default (female)' do
expect(subject.send(method, 'FOOBAR')).to eq 'female'
end
Will fail because value == 'FOOBAR' and default_proc.call == 'female' so the call looks like @wrapper.load('FOOBAR' || 'female') which will favor the 'FOOBAR' and the load returns nil.
|
whoops... make sure to check the "outdated diff" comments ;) |
|
@sled what is stopping us from changing class Enum
include Base
def initialize(values, default = nil)
# ... setup
self.default(default)
end
def default(value)
raise ArgumentError, 'invalid value' unless ...
@default_proc = value.respond_to?(:call) ? value : -> { value }
self
end
endi.e. why not simply override In the end that way I'm sure we can properly handle defaults in a general and Enum-specific way. |
|
Sure we can directly do it in the enum. The big Q is whether the load/dump logic should be applied to the default as with any other other value. E.g |