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

Cache result of validation once outcome is done #411

Closed
lulalala opened this issue Mar 28, 2017 · 11 comments
Closed

Cache result of validation once outcome is done #411

lulalala opened this issue Mar 28, 2017 · 11 comments
Assignees
Labels
Milestone

Comments

@lulalala
Copy link
Contributor

This is just throwing some ideas.

Currently, if we call outcome.valid?, it would re-evaluate all the validations again.

If one validation is not idempotent, for example checking if it is run on weekdays, it can results in inconsistency between outcome object and its valid? results. (Say we run it on Friday 23:59 and then the controller gets to check its validity on Saturday 00:01)

Would it makes sense to provide some caching mechanism, so that once outcome is done, outcome's error result can be cached, so that validations won't be run again?

@lulalala
Copy link
Contributor Author

lulalala commented Mar 29, 2017

Just realized that there already exists some caching, checking for @_interaction_valid.

It's just that if interaction fails during validation phase, result= is never called, thus that will not be assigned.

Would something like this work?

    def valid?
      if instance_variable_defined?(:@_interaction_valid)
        return @_interaction_valid
      end

      @_interaction_valid = super
    end

==UPDATE==

The above would not work, if validations are successful, but some errors happens during execute, it would result in a failed yet valid outcome. I guess the way to do it would be like this:

    def run # rubocop:disable MethodLength
      if !valid?
        @_interaction_valid = false
        return
      end

This way if it validates successfully, the results won't be cached yet, allowing it to be set after execute.

@AaronLasseigne
Copy link
Owner

So it's valid and you get an outcome but then when you call valid again it's failing?

@lulalala
Copy link
Contributor Author

@AaronLasseigne actually it is the opposite: only when validation fails, would calling valid? reevaluate it again. So it can validate to failure, and we call valid? later and get true back.

@AaronLasseigne
Copy link
Owner

For a test I used:

class I < ActiveInteraction::Base
  VALID = [false, true].cycle

  validate do |interaction|
    interaction.errors.add(:base, 'failed') if !VALID.next
  end

  def execute; end
end

I was able to cache the result by changing valid?.

    def valid?(*)
      if instance_variable_defined?(:@_interaction_valid)
        return @_interaction_valid
      end

      valid = super
      self.result = nil unless valid
      valid
    end

This seems to have fixed the issue.

@AaronLasseigne
Copy link
Owner

@tfausak we let people modify the value of an input but it doesn't change the result attached to the outcome. Do you remember why we allow that?

@tfausak
Copy link
Collaborator

tfausak commented Apr 14, 2017

I don't remember why we do that.

@AaronLasseigne
Copy link
Owner

After thinking about this some I think it's a great idea. We should always cache the result and we shouldn't let people modify the inputs. That makes the whole process more immutable. I think this would probably require a major version bump though. We have a few other things that also need a major bump so maybe it's time.

@tfausak tfausak added this to the v4.0.0 milestone Apr 17, 2017
@tfausak
Copy link
Collaborator

tfausak commented Apr 17, 2017

Makes sense. We'll have to make sure we don't mess up using interactions in forms if they're immutable.

@AaronLasseigne AaronLasseigne self-assigned this May 11, 2017
@AaronLasseigne
Copy link
Owner

@lulalala I believe this will fix the issue you were having. Once run (or run!) is called and an outcome is produced, the result and the validity of that outcome are immutable.

It'll be part of the 4.0.0 release.

@lulalala
Copy link
Contributor Author

lulalala commented Jan 9, 2018

I just met another bug, where I have a callback, and calling valid? caused that callback to be called twice. The 4.0.0 branch fixed this. Cheers!

@AaronLasseigne
Copy link
Owner

I decided to go ahead and release this as a bug fix in v3.6.2.

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

No branches or pull requests

3 participants