solnic / virtus

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

Strict mode only works for basic values #393

Open arianf opened 5 years ago

arianf commented 5 years ago
require 'virtus'

class SomeRandomClass
end

class User
  include Virtus.model(strict: true)

  attribute :some_ran_class, SomeRandomClass
end

User.new(some_ran_class: 5) # no error

User.new() # no error

User.new(some_ran_class: SomeRandomClass.new) # should be the only one that doesn't cause an error
arianf commented 5 years ago

This is because if the type is not a recognized primitive, it defaults to Object, and coercing an object to an object will always work.

But I feel like if you have strict mode enabled, you should only be able to have the Class type you specified

celesteking commented 5 years ago

Just came across this - what's the sense of specifying attribute type if that type isn't honored? That's a total disaster. You can assign random things to attribute and there's no casting done when you supply virtus model #new with a hash of stuff.

arianf commented 5 years ago

@celesteking you should check out https://github.com/AaronLasseigne/active_interaction

It’s a much better implementation

celesteking commented 5 years ago

Me? Nope, because it's 3rd party (elasticsearch-persistence) that's using this stale software. Anyways, I've managed to find a workaround:

require 'ipaddr'

class Mymodel
  include Virtus.model

  class TypeCoercer
    define_singleton_method(:[]) do |cast_type|
      Class.new(Virtus::Attribute).class_eval do
        define_method(:coerce) do |value|
          value && cast_type.new(value)
        end
        self
      end
    end
  end

  attribute :myattr, TypeCoercer[IPAddr], default: nil
end

puts Mymodel.new(myattr: '1.2.3.4').myattr.class

VIRTUS CUSTOM COERCION NOT WORKING attribute not coercing