remi-add_hook 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc ADDED
@@ -0,0 +1 @@
1
+ see Object#add_hook
data/Rakefile ADDED
@@ -0,0 +1,66 @@
1
+ require 'rake'
2
+ require 'rubygems'
3
+ require 'rake/rdoctask'
4
+ require 'spec/rake/spectask'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |s|
9
+ s.name = 'add_hook'
10
+ s.summary = 'Easily add callbacks to any method'
11
+ s.email = 'remi@remitaylor.com'
12
+ s.homepage = 'http://github.com/remi/add_hook'
13
+ s.description = 'Easily add callbacks to any method'
14
+ s.authors = %w( remi )
15
+ s.files = FileList['[A-Z]*', '{lib,spec,bin,examples}/**/*']
16
+ # s.add_dependency 'person-gemname'
17
+ # s.executables << 'script'
18
+ # s.rubyforge_project = 'gemname'
19
+ # s.extra_rdoc_files = %w( README.rdoc )
20
+ end
21
+ rescue LoadError
22
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
23
+ end
24
+
25
+ Spec::Rake::SpecTask.new do |t|
26
+ t.spec_files = FileList['spec/**/*_spec.rb']
27
+ end
28
+
29
+ desc "Run all examples with RCov"
30
+ Spec::Rake::SpecTask.new('rcov') do |t|
31
+ t.spec_files = FileList['spec/**/*_spec.rb']
32
+ t.rcov = true
33
+ end
34
+
35
+ # require 'hanna'
36
+ # require 'darkfish-rdoc'
37
+
38
+ Rake::RDocTask.new do |rdoc|
39
+ rdoc.rdoc_dir = 'rdoc'
40
+ rdoc.title = 'add_hook'
41
+ rdoc.options << '--line-numbers' << '--inline-source'
42
+ # rdoc.options += ["--template=#{`allison --path`}"] # sudo gem install allison
43
+ # rdoc.options += %w( -f darkfish ) # sudo gem install darkfish-rdoc
44
+ # rdoc.options += %w( -T hanna ) # sudo gem install mislav-hanna
45
+ rdoc.options += %w( -m README.rdoc ) # the initial page displayed
46
+ rdoc.rdoc_files.include('README.rdoc')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
49
+
50
+ desc 'Confirm that gemspec is $SAFE'
51
+ task :safe do
52
+ require 'yaml'
53
+ require 'rubygems/specification'
54
+ data = File.read('add_hook.gemspec')
55
+ spec = nil
56
+ if data !~ %r{!ruby/object:Gem::Specification}
57
+ Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
58
+ else
59
+ spec = YAML.load(data)
60
+ end
61
+ spec.validate
62
+ puts spec
63
+ puts "OK"
64
+ end
65
+
66
+ task :default => :spec
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 1
data/lib/add_hook.rb ADDED
@@ -0,0 +1,68 @@
1
+ class Object
2
+
3
+ # Add as a callback to an instance method
4
+ #
5
+ # ==== Usage
6
+ #
7
+ # >> x = [1, 2]
8
+ # => [1, 2]
9
+ # >> x.add_hook(:<<){|the_array, *args| puts "called #{ the_array.inspect } << #{ args.inspect }" }
10
+ # => nil
11
+ # >> x << 'foo'
12
+ # called [1, 2] << ["foo"]
13
+ # => [1, 2, "foo"]
14
+ #
15
+ # ==== Parameters
16
+ # method_name<~to_s>::
17
+ # The name of the method to add a hook to
18
+ #
19
+ # &block::
20
+ # A block to run everytime the method gets called.
21
+ # The block is passed multiple arguments.
22
+ # The first argument is self, the instance that the method is being called on.
23
+ # The rest of the arguments are the arguments that were passed to the method.
24
+ #
25
+ def add_hook method_name, &block
26
+
27
+ # protect against infinite looping
28
+ return if method_name.to_s == 'add_hook'
29
+
30
+ # if we haven't hooked into any methods on this instance yet
31
+ # then we need to add a way to persist our hooked methods and callbacks
32
+ unless self.respond_to? :hooked_methods
33
+
34
+ # add some things to this particular object
35
+ class << self
36
+ attr_accessor :hooked_methods, :hooked_method_hooks
37
+ end
38
+
39
+ # initalize attributes
40
+ self.hooked_methods ||= { }
41
+ self.hooked_method_hooks ||= { }
42
+
43
+ end
44
+
45
+ # for now, assume this is an *instance method* that we're hooking
46
+ method = self.class.instance_method(method_name.to_s)
47
+ method_key = method_name.to_s + Time.now.to_s
48
+
49
+ if method
50
+
51
+ self.hooked_methods[ method_key ] = method # store the original method
52
+ self.hooked_method_hooks[ method_key ] = block # store the block to call
53
+
54
+ # using eval because define_method can't create
55
+ # a method that accepts a block
56
+ eval %{
57
+ def self.#{ method_name } *args #, &block
58
+ self.hooked_method_hooks[#{ method_key.inspect }].call(self, *args)
59
+ self.hooked_methods[#{ method_key.inspect }].bind(self).call(*args) # add block
60
+ end
61
+ }
62
+
63
+ else
64
+ raise "Cannot find method #{ method_name.inspect } to add hook to"
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/../lib/add_hook'
2
+
3
+ def main_method first_arg, second_arg, *splat_of_args
4
+ end
5
+
6
+ describe Object, '#add_hook' do
7
+
8
+ it 'should be able to add a hook to an object in the main scope' do
9
+ times_called = 0
10
+
11
+ main_method 1, 2, 3, 4, 5
12
+ times_called.should == 0
13
+
14
+ add_hook(:main_method) do |obj, *args|
15
+ # puts "called main_method on #{ obj } with args: #{ args.inspect }"
16
+ times_called += 1
17
+ end
18
+
19
+ times_called.should == 0
20
+ main_method 1, 2, 3, 4, 5
21
+ times_called.should == 1
22
+ end
23
+
24
+ it 'should be able to add a hook to objects' do
25
+ object = []
26
+ times_called = 0
27
+
28
+ object << 'x'
29
+ times_called.should == 0
30
+
31
+ object.add_hook(:<<){|obj, *args| times_called += 1 }
32
+
33
+ object << 'x'
34
+ times_called.should == 1
35
+
36
+ object << 'x'
37
+ times_called.should == 2
38
+
39
+ # should not effect other arrays
40
+ object = []
41
+ object << 'x'
42
+ times_called.should == 2 # should still be 2
43
+ end
44
+
45
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format specdoc
3
+ --loadby mtime
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remi-add_hook
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - remi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-06 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Easily add callbacks to any method
17
+ email: remi@remitaylor.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - Rakefile
26
+ - VERSION.yml
27
+ - README.rdoc
28
+ - lib/add_hook.rb
29
+ - spec/add_hook_spec.rb
30
+ - spec/spec.opts
31
+ has_rdoc: true
32
+ homepage: http://github.com/remi/add_hook
33
+ post_install_message:
34
+ rdoc_options:
35
+ - --inline-source
36
+ - --charset=UTF-8
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ requirements: []
52
+
53
+ rubyforge_project:
54
+ rubygems_version: 1.2.0
55
+ signing_key:
56
+ specification_version: 2
57
+ summary: Easily add callbacks to any method
58
+ test_files: []
59
+