cgriego / active_attr

What ActiveModel left out
MIT License
1.2k stars 91 forks source link

an inline proc/lambda typecaster executes in the instance context #187

Open dmgr opened 3 years ago

dmgr commented 3 years ago

When using an inline proc/lambda typecaster it should be run in the context of the object thus you can use its methods. In short we binds typecaster to the object.

cgriego commented 2 years ago

@dmgr Do you have an example use case for this? I'm trying to wrap my head around why this would be desirable, especially since this isn't something that I know to be supported in ROM/dry-types, ActiveRecord, Mongoid, etc.

dmgr commented 2 years ago

The usecase is similar to default: option behavior: https://github.com/cgriego/active_attr/blob/55406079d70171df8bccfeb9b4eb2e98a02f58ab/lib/active_attr/attribute_defaults.rb#L114

By the way, the:

    when default.respond_to?(:call) then instance_exec(&default)

should be

    when default.is_a?(Proc) then instance_exec(&default)

in my opinion as you can only use procs/lambdad in instance_exec and not and object with a .call method, otherwise you will get an error:

wrong argument type Xxx (expected Proc) (TypeError)

If you really want to use a #call method of the object, you should rather do:

    when default.is_a?(Proc) then instance_exec(&default)
    when default.respond_to?(:call) then instance_exec(&default.method(:call))

but I discourage doing so as it may have unpredictable side-effect depends on how default object is implemented. It would be more safe to execute only procs/lambdas in the context of attributes object, but not objects that implements #call method. So the final code snippet for lib/active_attr/attribute_defaults.rb#L114 would be:

    when default.is_a?(Proc) then instance_exec(&default)