-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Arbitrary object interfaces (duck types) as parameters? #178
Comments
Duck typing is something we've considered. We discussed it in the initial implementation and decided to wait until there was a real need for it. And here it is! Looking at how Mutations implements it, you can do this now with custom validators. This is obviously not ideal, but it's a workaround. class DuckInteraction < ActiveInteraction::Base
model :duck, class: Object, methods: %i[foo bar]
validate do
attribute = :duck
input = inputs[attribute]
self.class.filters.fetch(attribute).options.fetch(:methods).each do |method|
unless input.respond_to?(method)
errors.add_sym(attribute, :invalid_duck, "does not respond to #{method}")
end
end
end
end I think we could implement a
|
Can you provide a bit more information about what you're trying to fix? You mention introducing a dependency on a "real live model". Are you trying to avoid database calls? Have you considered using mock_model? |
@AaronLasseigne No, I didn't know about This came up as I was adapting a class originally written against Mutations to ActiveInteraction. I'm publishing my little interactor-exploration project; you can find the original Mutation-based spec here and class here. |
Yeah, after a quick read of the Filter source, 179 looks like it could be a real can of worms. (Do you really want to depend on somebody else's code lying to itself and everybody else about what it is?) Duck-type filters would sidestep that whole problem entirely. Imagine that I use @tfausak's |
How is that any worse than relying on duck typing? Somebody else's code could be lying to itself and everybody else about what methods it implements. class Liar
def respond_to?(*)
true
end
end Looking at your class DummyBlog
def is_a?(klass)
klass == Blog || super
end
end Then, pending the fix to #179, everything would work fine. |
It's "worse than relying on duck typing" because, with duck typing, you can still write a simple PORO that plays by the rules ( |
I want to clarify a possible point of confusion. The The |
Ah. Light dawns, at 4 AM. (thud) That was not clear from reading the doc and specs; it most certainly should (in conjunction with the fix for 179) address my use case. After turning "should" into "does", I'd like to submit a pull request adding some verbiage to the README (under "How do I define an interaction?", most likely) so that the next guy making this transition doesn't step on the same banana peels I did. Thanks very much! |
Thanks for working with us to get to the bottom of this! Version 1.2.1 has been released with a fix for #179. In addition, we've decided to add duck typing to version 1.3.0 via an You've also encouraged us to make our documentation better. If you want to lend a hand with that, check out #183. |
Issue #169 touched on this; one very important distinction between ActiveInteraction and its credited inspiration in Mutations is support for duck typing. In Mutations, I can have an attribute whitelist declaration such as
and then pass in a bespoke PORO implementing these methods during unit testing, or an
ActiveRecord::Base
subclass instance in integration test or production. With ActiveInteraction, I have to resort to code in my specs such asThis feels like it makes my tests more brittle because it introduces a dependency on a real live model instance (even with all the stubbing).
The text was updated successfully, but these errors were encountered: