Support for Guard gem

I know this sound a lot like an xkcd://1172: Every change breaks someone’s workflow, but I can try to don’t.

While I was trying to formulate a Proof of concept of a bug related to Dry-Validation I though it was a good idea to spin my local Guard and start iterating my case using an new spec file (and being sure I didn’t break some other spec also). When I tried to use Guard got this error:

Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/guard-rspec-4.7.3/lib/guard/rspec_defaults.rb:1:in `<top (required)>': Guard is not a module (TypeError)

Going deep on this, turns out Dry Validation defines a class called Guard, specifically Dry::Validation::Guard in lib/dry/validation/schema_compiler.rb, since is a class, Guard gem cannot work as intended because expect to be a module.

Is there any chance to rename the conflicting class to something like Dry::Validation::InternalGuard? The following diff made possible to continue working with Guard as expected:

diff --git a/lib/dry/validation/executor.rb b/lib/dry/validation/executor.rb                     │
index 330be83..11ab58e 100644                                                                    │
--- a/lib/dry/validation/executor.rb                                                             │
+++ b/lib/dry/validation/executor.rb                                                             │
@@ -45,7 +45,7 @@ module Dry                                                                     │
       def call(input, result)                                                                   │
         rules.each_with_object(result) do |(name, checks), hash|                                │
           checks.each do |check|                                                                │
-            check_res = check.is_a?(Guard) ? check.(input, result) : check.(input)              │
+            check_res = check.is_a?(InternalGuard) ? check.(input, result) : check.(input)      │
             if hash.key?(name)                                                                  │
               if hash[name].is_a?(Array)                                                        │
                 hash[name] << check_res


diff --git a/lib/dry/validation/schema_compiler.rb b/lib/dry/validation/schema_compiler.rb       │
index 240345b..1878093 100644                                                                    │
--- a/lib/dry/validation/schema_compiler.rb                                                      │
+++ b/lib/dry/validation/schema_compiler.rb                                                      │
@@ -2,7 +2,7 @@ require 'dry/logic/rule_compiler'                                                │
                                                                                                 │
 module Dry                                                                                      │
   module Validation                                                                             │
-    class Guard                                                                                 │
+    class InternalGuard                                                                         │
       attr_reader :rule, :deps                                                                  │
                                                                                                 │
       def initialize(rule, deps)                                                                │
@@ -70,7 +70,7 @@ module Dry                                                                     │
                                                                                                 │
       def visit_guard(node)                                                                     │
         deps, other = node                                                                      │
-        Guard.new(visit(other), deps)                                                           │
+        InternalGuard.new(visit(other), deps)                                                   │
       end                                                                                       │
                                                                                                 │
       def visit_type(type)

Of course I’d understand if this is not possible.

The proper fix is to add require 'dry/validation/schema_compiler' at the top of dry/validation/executor.rb

I tried that fix and still have the same problem.

For some reason while running any spec through Guad/RSpec, for ruby interpreter there’s a constant called Guard even if it’s namespaced as Dry::Validation::Guard, so later on, guard-rspec tries to redefine Guard as a module making ruby not happy as in running like this:

class Guard
end
# => nil
module Guard
end
TypeError: Guard is not a module
        from (irb):3
        from /Users/esparta/.rvm/rubies/ruby-2.2.9/bin/irb:11:in `<main>'

While we mean to run like this:

module Dry
  module Validation
    class Guard
    end
  end
end
# => nil
module Guard
end
# => nil
Dry::Validation::Guard.class
#  => Class
Guard.class
# => Module

Looks like there’s a lot of unknown facts on my stack (Guard + Guard/RSpec) and is not worthy to continue digging since there’s no use case and I’m the only one using it :slight_smile:

Thanks for your help and time.

Tracelog:

23:18:53 - INFO - Running: spec/integration/schema/nested_schemas_two_spec.rb
/Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/guard-rspec-4.7.3/lib/guard/rspec_defaults.rb:1:in `<top (required)>': Guard is not $
 module (TypeError)
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/guard-rspec-4.7.3/lib/guard/rspec_formatter_results_path.rb:1:in `requi$
e_relative'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/guard-rspec-4.7.3/lib/guard/rspec_formatter_results_path.rb:1:in `<top $
required)>'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/guard-rspec-4.7.3/lib/guard/rspec_formatter.rb:10:in `require_relative'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/guard-rspec-4.7.3/lib/guard/rspec_formatter.rb:10:in `<top (required)>'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in `require'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in `block in requ$
res='
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in `each'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in `requires='
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:112:in `block $
n process_options_into'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:111:in `each'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:111:in `proces$
_options_into'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:21:in `configu$
e'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:99:in `setup'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:86:in `run'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:71:in `run'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:45:in `invoke'

        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/gems/rspec-core-3.7.1/exe/rspec:4:in `<top (required)>'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/bin/rspec:23:in `load'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/bin/rspec:23:in `<main>'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/bin/ruby_executable_hooks:15:in `eval'
        from /Users/esparta/.rvm/gems/ruby-2.2.9@dry-rb/bin/ruby_executable_hooks:15:in `<main>'