Skip to content
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

Fix validation callback order #196

Closed
tfausak opened this issue May 28, 2014 · 1 comment
Closed

Fix validation callback order #196

tfausak opened this issue May 28, 2014 · 1 comment
Assignees
Milestone

Comments

@tfausak
Copy link
Collaborator

tfausak commented May 28, 2014

Validation callbacks don't happen when I expect them to. Consider the following interaction.

class Interaction < ActiveInteraction::Base
  validate do
    p :validate
  end

  set_callback :validate, :before do
    p :validate_before
  end

  set_callback :validate, :after do
    p :validate_after
  end

  set_callback :validate, :around do |_, block|
    p :validate_around_before
    block.call
    p :validate_around_after
  end
end

I would expect the validation callbacks to be executed around the validate block. But that's not what happens. This is what that interaction outputs.

:validate
:validate_before
:validate_around_before
:validate_around_after
:validate_after

This is because validate itself is implemented as a callback (source). This is a problem for ActiveInteraction because we use validate to validate inputs (source). @nilcolor discovered this in #195.

As far as I can tell, the only reliable way to get our validation to happen where we want it is to override run_validations!. (You can see from the source that it doesn't provide a block to run_callbacks. That means around callbacks are executed around nothing.) I'm a little hesitant to do this because we can't call super; it would end up running the callbacks twice.

This is particularly frustrating because the documentation for validate suggests there's a validate instance method we could override. The link leads back to itself, but I think it's talking about this one.

@tfausak tfausak added the bug label May 28, 2014
@tfausak tfausak self-assigned this May 28, 2014
@tfausak
Copy link
Collaborator Author

tfausak commented May 28, 2014

@AaronLasseigne and I talked this over in person. The problem with overriding run_validations! is that any validations would be run before validating inputs. So that's a non-starter.

One way out of this would be to introduce the validation callback, which is separate from the validate callback. Our input validation would be part of validate, and any user-defined validation should be part of validation. Even though this is what ActiveRecord does, I'm not a fan; the difference between validation and validate is too subtle and easy to mess up.

Another way out of this is to add a third callback for type checking. It would happen before validation. The callback flow would look like this:

:type_check
:validate
:execute

It might make sense to prevent validation if type checking fails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant