remi-add_hook 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+