wrapr 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ vendor/*
6
+ .idea/*
7
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in wrapr.gemspec
4
+ gemspec
@@ -0,0 +1,34 @@
1
+ Wrapr
2
+ ====
3
+
4
+ Modify class behavior at runtime. Similar to before/after/around filters in Rails ActionController::Base
5
+
6
+ Example
7
+ ------
8
+
9
+ require 'wrapr'
10
+ require 'logger'
11
+ log = Logger.new(STDOUT)
12
+
13
+ Wrapr::Wrapr.new(Exception).before(:initialize) do |this,*args|
14
+ log.debug("New exception is being created "+args.inspect)
15
+ args
16
+ end
17
+
18
+ 5/0 # we can hijack any class's instance methods and inject our own functionality
19
+
20
+
21
+ Potential Uses
22
+ --------------
23
+
24
+ Use with ruby-debug to set conditional break points
25
+
26
+ require 'ruby-debug'
27
+ Wrapr::Wrapr.new(Post).before(:find) do |this,*args|
28
+ # Open debug when a post is instantiated
29
+ debugger if args[:conditions][:
30
+ args
31
+ end
32
+
33
+ Use with analytics packages to track application events from a single location
34
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,34 @@
1
+ # These examples written for samples of code in the documentation
2
+
3
+ $: << File.dirname(__FILE__)+"/lib"
4
+ require 'wrapr'
5
+ require 'logger'
6
+ log = Logger.new(STDOUT)
7
+
8
+
9
+
10
+
11
+ w = Wrapr::Wrapr.new(Exception)
12
+ # #before can mutate the instance and args as well
13
+ w.before(:initialize) do |this,*args|
14
+ args[0].upcase!
15
+ args
16
+ end
17
+ puts Exception.new("foo").to_s # FOO
18
+ w.around(:to_s) do |this,method,*args|
19
+ puts "Before to_s"
20
+ result = method.call()
21
+ result+=" "
22
+ end
23
+ puts Exception.new("foo").to_s # FOO, "Before to_s OOF "
24
+ w.after(:to_s) do |this,result|
25
+ result.downcase
26
+ end
27
+ puts Exception.new("foo").to_s # FOO, "Before to_s foo"
28
+
29
+ Wrapr::Wrapr.new(Exception).before(:initialize) do |this,*args|
30
+ log.debug("New exception is being created "+args.inspect)
31
+ args
32
+ end
33
+
34
+ 5/0
@@ -0,0 +1,86 @@
1
+ require "wrapr/version"
2
+
3
+ module Wrapr
4
+
5
+
6
+
7
+
8
+ # Allows method wrapping
9
+ #
10
+ # Usage
11
+ # w = Wrapr::Wrapr.new(Exception)
12
+ # # #before can mutate the instance and args as well
13
+ # w.before(:initialize) do |this,*args|
14
+ # args[0].upcase!
15
+ # args
16
+ # end
17
+ # puts Exception.new("foo").to_s # FOO
18
+ # w.around(:to_s) do |this,method,*args|
19
+ # puts "Before to_s"
20
+ # result = method.call()
21
+ # result+=" "
22
+ # end
23
+ # puts Exception.new("foo").to_s # FOO, "Before to_s OOF "
24
+ # w.after(:to_s) do |this,result|
25
+ # result.downcase
26
+ # end
27
+ # puts Exception.new("foo").to_s # FOO, "Before to_s foo"
28
+
29
+ class Wrapr
30
+ def initialize(klass)
31
+ @klass=klass
32
+ end
33
+ # Executes block around
34
+ # Call of wrapped method is responsibility of the passed block
35
+ #
36
+ # Transparently
37
+ #
38
+ # Wrapr.new(Exception).around(:to_s) { |self,method,*outer_args|
39
+ # method.call(*outer_args)
40
+ # }
41
+ def around(method,&block)
42
+ # fetch the unbound instance method
43
+ unbound = @klass.instance_method(method)
44
+ @klass.class_eval do
45
+ # create a new method with the same name
46
+ define_method(method) do |*outer_args|
47
+ # we pass the current instance and overridden method
48
+ block.call(self,unbound.bind(self),*outer_args)
49
+ # We cannot do self.send(method,...) because we are redefining @method, causes recursion
50
+ end
51
+ end
52
+ end
53
+ # Executes block before method is called
54
+ # Passes the return of the block to method
55
+ #
56
+ # Transparent before
57
+ #
58
+ # Wrapr.new(Exception).before(:to_s) { |self,*outer_args|
59
+ # return outer_args
60
+ # }
61
+ def before(method,&block)
62
+ unbound = @klass.instance_method(method)
63
+ @klass.class_eval do
64
+ define_method(method) do |*outer_args|
65
+ unbound.bind(self).call(*block.call(self,*outer_args))
66
+ end
67
+ end
68
+ end
69
+ # Executes block after method is called
70
+ # Passes the response of method into block
71
+ #
72
+ # Transparent after
73
+ #
74
+ # Wrapr.new(Exception).after(:to_s) do |self,*result|
75
+ # return result
76
+ # end
77
+ def after(method,&block)
78
+ unbound = @klass.instance_method(method)
79
+ @klass.class_eval do
80
+ define_method(method) do |*outer_args|
81
+ block.call(self, *unbound.bind(self).call(*outer_args))
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,3 @@
1
+ module Wrapr
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,81 @@
1
+ require 'wrapr'
2
+ describe Wrapr::Wrapr do
3
+ before do
4
+ class Foo
5
+ attr_accessor :stack
6
+ def initialize
7
+ @stack = [:initialize]
8
+ end
9
+ def instance_m
10
+ @stack.push([:instance_m])
11
+ end
12
+ def instance_m_arg(x)
13
+ @stack.push x
14
+ end
15
+ def self.static_m(stack,item)
16
+ stack << item
17
+ end
18
+ end
19
+ @wrapper = Wrapr::Wrapr.new(Foo)
20
+ end
21
+ context "around" do
22
+ it "wraps something around a method" do
23
+ @wrapper.around(:instance_m) do |this,method,*args|
24
+ this.stack << :around_before
25
+ method.call(*args)
26
+ this.stack << :around_after
27
+ end
28
+ instance = Foo.new
29
+ instance.instance_m
30
+ instance.stack.should include(:around_before,:around_after)
31
+ end
32
+ it "even works with arguments" do
33
+ @wrapper.around(:instance_m) do |this,method,a,b|
34
+ this.stack << a << b
35
+ method.call()
36
+ end
37
+ instance = Foo.new
38
+ instance.instance_m(:argument_one,:argument_two)
39
+ instance.stack.should include(:argument_one,:argument_two)
40
+ end
41
+ it "even works with layers of arguments" do
42
+ @wrapper.around(:instance_m_arg) do |this,method,a,b|
43
+ this.stack.push(b)
44
+ method.call( (a.to_s+b.to_s).to_sym )
45
+ end
46
+ instance = Foo.new
47
+ instance.instance_m_arg(:argument_one, :argument_two)
48
+ instance.stack.should_not include(:argument_one)
49
+ instance.stack.should include(:argument_oneargument_two)
50
+ end
51
+ end
52
+ context "before" do
53
+ it "passes through arguments to a method" do
54
+ @wrapper.before(:instance_m_arg) do |this,x|
55
+ x.to_s
56
+ end
57
+ instance = Foo.new
58
+ instance.instance_m_arg(:argument)
59
+ instance.stack.should include("argument")
60
+ end
61
+ it "works transparently" do
62
+ @wrapper.before(:instance_m) do |this,*args|
63
+ this.stack.shift
64
+ args
65
+ end
66
+ instance = Foo.new
67
+ instance.instance_m
68
+ instance.stack.should_not include(:initialize)
69
+ end
70
+ end
71
+ context "after" do
72
+ it "passes return values into block" do
73
+ @wrapper.after(:instance_m) do |this,result|
74
+ result.to_s.upcase
75
+ end
76
+ instance = Foo.new
77
+ instance.instance_m.should == "INITIALIZE"
78
+ end
79
+ end
80
+ it "works with static methods"
81
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "wrapr/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "wrapr"
7
+ s.version = Wrapr::VERSION
8
+ s.authors = ["Thomas W. Devol"]
9
+ s.email = ["thomas.devol@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Allows before/around/after instance method wrapping}
12
+ s.description = s.summary+" etc..."
13
+
14
+ s.rubyforge_project = "wrapr"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wrapr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Thomas W. Devol
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-07 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70194634911940 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70194634911940
25
+ description: Allows before/around/after instance method wrapping etc...
26
+ email:
27
+ - thomas.devol@gmail.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - .rspec
34
+ - Gemfile
35
+ - README.md
36
+ - Rakefile
37
+ - informal_tests.rb
38
+ - lib/wrapr.rb
39
+ - lib/wrapr/version.rb
40
+ - spec/wrapr_spec.rb
41
+ - wrapr.gemspec
42
+ homepage: ''
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project: wrapr
62
+ rubygems_version: 1.8.10
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Allows before/around/after instance method wrapping
66
+ test_files:
67
+ - spec/wrapr_spec.rb