interceptor 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/MIT-LICENSE +19 -0
- data/README.md +54 -0
- data/interceptor.gemspec +18 -0
- data/lib/interceptor.rb +20 -0
- data/rakefile.rb +11 -0
- data/test/interceptor_test.rb +45 -0
- metadata +74 -0
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Ryan Allen, Envato Pty Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Interceptor
|
2
|
+
|
3
|
+
Mad Max had one, and he was freaking awesome.
|
4
|
+
|
5
|
+
## Overview:
|
6
|
+
|
7
|
+
Interceptor allows you to wrap other objects, and intercept method calls, without changing the target objects code, or performing any hairy metaprogramming. You may use this library to perform these kinds of tasks:
|
8
|
+
|
9
|
+
* Modifying method arguments as they come in.
|
10
|
+
* Modify return values as they go out.
|
11
|
+
* Perform other tasks (such as logging) without sprinkling the code throughout the objects (typically unrelated) implementation.
|
12
|
+
* Call completely different methods depending on anything you want, I suppose.
|
13
|
+
|
14
|
+
You can think of this as a more explicit form of AOP, but unlike AOP, instead of being picked off by a sniper from 3000m away (and being very surprised about the whole thing), it's like the sniper has arrived at your house with your birthday cake and birthday present in order to convey his birthday wishes.
|
15
|
+
|
16
|
+
## Example:
|
17
|
+
|
18
|
+
Let's say as a Ruby programmer you picked up some Lua and decided that Lua's idea of starting an Array at 1 is _way_ better than starting an Array at 0, in a fit of blinding genius you decide to make a Ruby Array behave like a Lua one.
|
19
|
+
|
20
|
+
lucky_numbers = [42, 666, 2012]
|
21
|
+
|
22
|
+
lucky_numbers[0] # => 42
|
23
|
+
lucky_numbers[1] # => 666
|
24
|
+
lucky_numbers[2] # => 2012
|
25
|
+
|
26
|
+
even_luckier_numbers = Interceptor.new(lucky_numbers)
|
27
|
+
|
28
|
+
# intercept the [] method, and take 1 off the index passed in
|
29
|
+
# so that our arrays become like lua arrays, kinda
|
30
|
+
even_luckier_numbers.intercept(:[]) do |receiver, target, index|
|
31
|
+
receiver[index-1]
|
32
|
+
end
|
33
|
+
|
34
|
+
even_luckier_numbers[1] # => 42
|
35
|
+
even_luckier_numbers[2] # => 666
|
36
|
+
even_luckier_numbers[3] # => 2012
|
37
|
+
|
38
|
+
The first two arguments to the block is a reference to the object passed to the Interceptor (in this case, a reference to ``lucky_numbers``), the second is a symbol of the method call (in this case, it is ``:[]``), and the remaining arguments are the arguments passed to the method call (in this case, ``1`` and ``2`` and ``3``).
|
39
|
+
|
40
|
+
## Patches:
|
41
|
+
|
42
|
+
What the hell is a patch?
|
43
|
+
|
44
|
+
## RubyGem?
|
45
|
+
|
46
|
+
Nope, how do you make those? I asked this guy called John and he told me to 'google it' or something.
|
47
|
+
|
48
|
+
## Mad Max:
|
49
|
+
|
50
|
+
Is freaking awesome, [here's proof](http://www.youtube.com/watch?v=nLCmcV4gC_0).
|
51
|
+
|
52
|
+
## Other Questions?
|
53
|
+
|
54
|
+
If you have any questions, shoot me a message on the github-o-sphere. I likely have no idea what you're talking about as I have no idea what I'm talking about most of the time.
|
data/interceptor.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'interceptor'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'interceptor'
|
7
|
+
s.version = Interceptor::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Ryan Allen']
|
10
|
+
s.email = ['ryan@ryanface.com']
|
11
|
+
s.homepage = 'https://github.com/ryan-allen/interceptor'
|
12
|
+
s.summary = %q{Mad Max had one, and he was freaking awesome.}
|
13
|
+
s.description = %q{Interceptor is a library for modifying calls to objects. You can change things as they come in or as they go out.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
end
|
data/lib/interceptor.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class Interceptor
|
2
|
+
VERSION = '0.0.1'
|
3
|
+
|
4
|
+
def initialize(receiver)
|
5
|
+
@receiver = receiver
|
6
|
+
@interceptions = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def intercept(*targets, &block)
|
10
|
+
targets.each { |target| @interceptions[target] = block }
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(target, *args, &block)
|
14
|
+
if @interceptions[target]
|
15
|
+
@interceptions[target].call(@receiver, target, *args, &block)
|
16
|
+
else
|
17
|
+
@receiver.send(target, *args, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/rakefile.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'interceptor'
|
3
|
+
|
4
|
+
class InterceptorTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@object = [1,3,2,5,4]
|
7
|
+
@wrapper = Interceptor.new(@object)
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_sort_works_as_we_expect_before_intercept
|
11
|
+
assert_equal [1,2,3,4,5], @wrapper.sort
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_our_sort_intercept_reverses_the_sort
|
15
|
+
@wrapper.intercept(:sort) { |r, t, *a| r.sort.reverse }
|
16
|
+
assert_equal [5,4,3,2,1], @wrapper.sort
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_we_are_passed_the_receiver
|
20
|
+
@wrapper.intercept(:[]) { |r, t, *a| r }
|
21
|
+
assert_equal @object, @wrapper[0]
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_we_are_passed_the_target
|
25
|
+
@wrapper.intercept(:[]) { |r, t, *a| t }
|
26
|
+
assert_equal :[], @wrapper[0]
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_we_are_passed_the_args
|
30
|
+
@wrapper.intercept(:[]) { |r, t, *a| a }
|
31
|
+
assert_equal [0], @wrapper[0]
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_that_the_block_is_like_totally_a_closure_and_shit!
|
35
|
+
@wrapper.intercept(:[]) { |r, t, *a| self.class }
|
36
|
+
assert_equal InterceptorTest, @wrapper[0]
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_can_wrap_more_than_one_method_in_a_single_call_and_can_differentiate_the_target_in_the_interception_phew_that_is_a_mouthful
|
40
|
+
@wrapper.intercept(:[], :sort, :reverse) { |r, t, *a| t }
|
41
|
+
assert_equal :[], @wrapper[0]
|
42
|
+
assert_equal :sort, @wrapper.sort
|
43
|
+
assert_equal :reverse, @wrapper.reverse
|
44
|
+
end
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: interceptor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ryan Allen
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-14 00:00:00 +10:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Interceptor is a library for modifying calls to objects. You can change things as they come in or as they go out.
|
23
|
+
email:
|
24
|
+
- ryan@ryanface.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- Gemfile
|
33
|
+
- MIT-LICENSE
|
34
|
+
- README.md
|
35
|
+
- interceptor.gemspec
|
36
|
+
- lib/interceptor.rb
|
37
|
+
- rakefile.rb
|
38
|
+
- test/interceptor_test.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: https://github.com/ryan-allen/interceptor
|
41
|
+
licenses: []
|
42
|
+
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
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
|
+
hash: 3
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.7
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Mad Max had one, and he was freaking awesome.
|
73
|
+
test_files:
|
74
|
+
- test/interceptor_test.rb
|