Permalink
Browse files

watcher init now has an addition param that allows the user to return…

… any obj type. The spec has been restored to its original and then more specs added for object support.
  • Loading branch information...
1 parent d6b47f6 commit 33542acec9b53bb7e167f9ab192d38c408b54a49 @earlonrails committed Oct 7, 2011
Showing with 108 additions and 29 deletions.
  1. +12 −7 lib/guard/watcher.rb
  2. +96 −22 spec/guard/watcher_spec.rb
View
@@ -6,15 +6,15 @@ module Guard
#
class Watcher
- attr_accessor :pattern, :action
+ attr_accessor :pattern, :action, :any_rtn
@netzpirat

netzpirat Oct 9, 2011

You saved three characters in any_rtn and everybody looking at this in half a year needs three seconds more until he get the point.

# Initialize a file watcher.
#
# @param [String, Regexp] pattern the pattern to be watched by the guard
# @param [Block] action the action to execute before passing the result to the Guard
#
- def initialize(pattern, action = nil)
- @pattern, @action = pattern, action
+ def initialize(pattern, action = nil, any_rtn = false)
@netzpirat

netzpirat Oct 9, 2011

Always add new parameters to the documentation.

+ @pattern, @action, @any_rtn = pattern, action, any_rtn
@@warning_printed ||= false
# deprecation warning
@@ -38,21 +38,26 @@ def initialize(pattern, action = nil)
#
# @param [Guard::Guard] guard the guard which watchers are used
# @param [Array<String>] files the changed files
- # @return [Array<String>] the matched files
- # @optional_return [Anything] return whatever you want to path
+ # @return [Array<Object>] the matched watcher response
@rymai

rymai Oct 10, 2011

Please add a blank commented line here (before the method signature). :)

def self.match_files(guard, files)
guard.watchers.inject([]) do |paths, watcher|
@rymai

rymai Oct 10, 2011

BTW, it now feels wrong to me to call the accumulator paths when it can now be populated by any objects.

+ wa = watcher.any_rtn
@netzpirat

netzpirat Oct 9, 2011

Here you still would know what wa means, if you understand any_rtn.

files.each do |file|
if matches = watcher.match_file?(file)
if watcher.action
result = watcher.call_action(matches)
- paths << result
+ if wa
@netzpirat

netzpirat Oct 9, 2011

Was it a watcher action or a watcher array? Ah. watch anything? You can simply check if something is idiomatic Ruby or not: Try to read it aloud.

+ paths << result
+ elsif result.respond_to?(:empty?) && ! result.empty?
@rymai

rymai Oct 10, 2011

You can safely remove the space after !. Now it feels like the poor ! is lost between dad && and mom result.empty? but is really belonging to mom here! :D

Btw, this entire if...elsif...end can probably be optimized, but don't bother with that now, we'll see what can be done later.

@netzpirat

netzpirat Oct 10, 2011

LOL. Where's mom?

+ paths << Array(result)
+ end
else
paths << matches[0]
end
end
end
- paths
+
+ wa ? paths : paths.flatten.map{|p| p.to_s}
@rymai

rymai Oct 10, 2011

Please add a space after { and before } here.

end
end
View
@@ -65,8 +65,8 @@
end
end
end
-
- context "with a watcher action without parameter" do
+
+ context "with a watcher action without parameter for a watcher that matches file strings" do
before(:all) do
@guard.watchers = [
described_class.new('spec_helper.rb', lambda { 'spec' }),
@@ -78,6 +78,43 @@
]
end
+ it "returns a single file specified within the action" do
+ described_class.match_files(@guard, ['spec_helper.rb']).should == ['spec']
+ end
+
+ it "returns multiple files specified within the action" do
+ described_class.match_files(@guard, ['hash.rb']).should == ['foo', 'bar']
+ end
+
+ it "returns multiple files by combining the results of different actions" do
+ described_class.match_files(@guard, ['spec_helper.rb', 'array.rb']).should == ['spec', 'foo', 'bar']
+ end
+
+ it "returns nothing if the action returns something other than a string or an array of strings" do
+ described_class.match_files(@guard, ['addition.rb']).should == []
+ end
+
+ it "returns nothing if the action response is empty" do
+ described_class.match_files(@guard, ['blank.rb']).should == []
+ end
+
+ it "returns nothing if the action returns nothing" do
+ described_class.match_files(@guard, ['uptime.rb']).should == []
+ end
+ end
+
+ context 'with a watcher action without parameter for a watcher that matches information objects' do
+ before(:all) do
+ @guard.watchers = [
+ described_class.new('spec_helper.rb', lambda { 'spec' }, true),
+ described_class.new('addition.rb', lambda { 1 + 1 }, true),
+ described_class.new('hash.rb', lambda { Hash[:foo, 'bar'] }, true),
+ described_class.new('array.rb', lambda { ['foo', 'bar'] }, true),
+ described_class.new('blank.rb', lambda { '' }, true),
+ described_class.new(/^uptime\.rb/, lambda { `uptime > /dev/null` }, true)
+ ]
+ end
+
it "returns a single file specified within the action" do
described_class.match_files(@guard, ['spec_helper.rb']).class.should == Array
described_class.match_files(@guard, ['spec_helper.rb']).empty?.should == false
@@ -104,16 +141,53 @@
described_class.match_files(@guard, ['uptime.rb']).should == ['']
end
end
-
- context "with a watcher action that takes a parameter" do
+
+ context "with a watcher action that takes a parameter for a watcher that matches file strings" do
+ before(:all) do
+ @guard.watchers = [
+ described_class.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }),
+ described_class.new(/addition(.*)\.rb/, lambda { |m| 1 + 1 }),
+ described_class.new('hash.rb', lambda { Hash[:foo, 'bar'] }),
+ described_class.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar'] }),
+ described_class.new(/blank(.*)\.rb/, lambda { |m| '' }),
+ described_class.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` })
+ ]
+ end
+
+ it "returns a substituted single file specified within the action" do
+ described_class.match_files(@guard, ['lib/my_wonderful_lib.rb']).should == ['spec/my_wonderful_lib_spec.rb']
+ end
+
+ it "returns multiple files specified within the action" do
+ described_class.match_files(@guard, ['hash.rb']).should == ['foo', 'bar']
+ end
+
+ it "returns multiple files by combining the results of different actions" do
+ described_class.match_files(@guard, ['lib/my_wonderful_lib.rb', 'array.rb']).should == ['spec/my_wonderful_lib_spec.rb', 'foo', 'bar']
+ end
+
+ it "returns nothing if the action returns something other than a string or an array of strings" do
+ described_class.match_files(@guard, ['addition.rb']).should == []
+ end
+
+ it "returns nothing if the action response is empty" do
+ described_class.match_files(@guard, ['blank.rb']).should == []
+ end
+
+ it "returns nothing if the action returns nothing" do
+ described_class.match_files(@guard, ['uptime.rb']).should == []
+ end
+ end
+
+ context "with a watcher action that takes a parameter for a watcher that matches information objects" do
before(:all) do
@guard.watchers = [
- described_class.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }),
- described_class.new(/addition(.*)\.rb/, lambda { |m| (1 + 1).to_s + m[0] }),
- described_class.new('hash.rb', lambda {|m| Hash[:foo, 'bar', :file_name, m[0]] }),
- described_class.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar', m[0]] }),
- described_class.new(/blank(.*)\.rb/, lambda { |m| '' }),
- described_class.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` })
+ described_class.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }, true),
+ described_class.new(/addition(.*)\.rb/, lambda { |m| (1 + 1).to_s + m[0] }, true),
+ described_class.new('hash.rb', lambda {|m| Hash[:foo, 'bar', :file_name, m[0]] }, true),
@rymai

rymai Oct 10, 2011

Space after {!

+ described_class.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar', m[0]] }, true),
+ described_class.new(/blank(.*)\.rb/, lambda { |m| '' }, true),
+ described_class.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` }, true)
]
end
@@ -143,18 +217,18 @@
end
context "with an exception that is raised" do
- before(:all) { @guard.watchers = [described_class.new('evil.rb', lambda { raise "EVIL" })] }
-
- it "displays the error and backtrace" do
- Guard::UI.should_receive(:error) { |msg|
- msg.should include("Problem with watch action!")
- msg.should include("EVIL")
- }
-
- described_class.match_files(@guard, ['evil.rb'])
- end
- end
- end
+ before(:all) { @guard.watchers = [described_class.new('evil.rb', lambda { raise "EVIL" })] }
+
+ it "displays the error and backtrace" do
+ Guard::UI.should_receive(:error) { |msg|
@rymai

rymai Oct 10, 2011

You should use do...end here since you have two lines in your block.

+ msg.should include("Problem with watch action!")
+ msg.should include("EVIL")
+ }
+
+ described_class.match_files(@guard, ['evil.rb'])
+ end
+ end
+ end
describe ".match_files?" do
before(:all) do

2 comments on commit 33542ac

Please don't take these comments personal. They just reflect my experience from working on very large codebases. They all start to rot with stuff that seems unimportant, but when you've them over and over your code, you'll start to have a serious problem.

I totally agree with you, I'd have had the same comments. :)

Please sign in to comment.