input variable is undefined when used in default lambda for another input variable
isfando opened this issue · 4 comments
class XYZ < ActiveInteraction::Base
object :foo, class: X, default: -> { baz&.contact }
object :bar, class: X, default: -> { X.unscoped.find(baz.duplicate_contact_id) }
object :baz, default: -> {
ContactDuplicateContact.where(contact_id: foo.id, duplicate_contact_id: bar.id).first!
}
def execute
...
end
end
When i call the interaction as following where "bar_obj" is not nil
XYZ.run!(baz: baz_obj)
the default initialization of "bar" fails with following error because it finds baz as undefined
NoMethodError:
undefined method `duplicate_contact_id' for nil:NilClass
I can circumvent the error by changing initialization order i.e. initializing baz as the first variable which makes the above scenario successful
class XYZ < ActiveInteraction::Base
object :baz, default: -> {
ContactDuplicateContact.where(contact_id: foo.id, duplicate_contact_id: bar.id).first!
}
object :foo, class: X, default: -> { baz&.contact }
object :bar, class: X, default: -> { X.unscoped.find(baz.duplicate_contact_id) }
def execute
...
end
end
BUT
it then fails when the interaction is called with
XYZ.run!(foo: foo_obj, bar:bar _obj)
the default initialization of "baz" fails with following error because it finds "foo" and "bar" as undefined
NoMethodError:
undefined method `id' for nil:NilClass
It look analogous to a circular dependency problem with defaults. One dirty solution where we expose extra complication and declare everything directly would be obviously this
baz_obj = get_baz_obj(..)
foo_obj = baz&.contact
bar_obj = X.unscoped.find(baz&.duplicate_contact_id)
XYZ.run!(baz: baz_obj, foo: foo_obj , bar: bar_obj )
BUT
Can anybody suggest a better way to solve this?
@AaronLasseigne , any guidance on this if possible
Yup, it's a circular dependency. I can't really offer help here. You'll have to rethink how you're approaching the problem. Best of luck.
class XYZ < ActiveInteraction::Base
object :foo, class: X, default: -> { baz&.contact }
object :bar, class: X, default: -> { X.unscoped.find(baz.duplicate_contact_id) }
object :baz, default: -> {
ContactDuplicateContact.where(contact_id: foo.id, duplicate_contact_id: bar.id).first!
}
def execute
...
end
end
When i call the interaction as following where "bar_obj" is not nil
XYZ.run!(baz: baz_obj)
But why is it undefined in default lambda of "bar", which fails with following error because it finds baz as undefined
NoMethodError:
undefined method `duplicate_contact_id' for nil:NilClass
We do checking of defaults early in process so it's running it and assigning it before the other objects have become available.