binding_ninja 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d3854a6100c403b0db08ad5f0c4c6c4e4b2c527
4
- data.tar.gz: b2b6748aa0b7c8195c94f69c5d80798908d87d69
3
+ metadata.gz: 57eeb87ad943b9ab0093e5cbbd33ee92891a2180
4
+ data.tar.gz: 1a5246c9bdb73a8b83ed7f01c5f61c6882df4349
5
5
  SHA512:
6
- metadata.gz: e62aebf9862aa927ef2112aa8f6abac2f4b85ac93bef9a4c15417e2bc720000ee21051c033acfc17a0585d302949d9aed8c56352e9df33aced3741a4efb41776
7
- data.tar.gz: af4d430af39734eaa1f63205aa4f115dc258eb4a724c2e662828d381d892056b29d3304ed1f3c626fb9baefc09058467202885029c1d40e826a7fe546aee3dba
6
+ metadata.gz: 1fadddaa3dd7b0f6cb31bbb9c1f531f4777ec83315b843fe7655cbcf49399ba3ae8e50e3a7288f6637d30e082374d9965d97ef36d073fe2ff24dd49bef57bacc
7
+ data.tar.gz: f7c154b4bc8de3a28e39c02ec4dd2645e82724839e843bdd9d71b6ab3af7891c5aa545d52c2274ce1cc7b8ec694fdb20d6ccfb7c97566552d951d03add4ffd4f
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # BindingNinja
2
+ [![Gem Version](https://badge.fury.io/rb/binding_ninja.svg)](https://badge.fury.io/rb/binding_ninja)
2
3
  [![Build Status](https://travis-ci.org/joker1007/binding_ninja.svg?branch=master)](https://travis-ci.org/joker1007/binding_ninja)
3
4
 
4
5
  This is method wrapper for passing binding of method caller implcitly.
6
+ And this is lightweight alternative of [binding_of_caller](https://github.com/banister/binding_of_caller)
5
7
 
6
8
  ## Installation
7
9
 
@@ -64,6 +66,70 @@ Foo.new.foo2(1, 2)
64
66
  `:if` option can accept Proc object and Symbol object.
65
67
  If option accepts a proc or symbol, uses result of evaluating the proc or method named by the symbol.
66
68
 
69
+ ## Compare to binding_of_caller
70
+ ```ruby
71
+ require "benchmark/ips"
72
+ require "binding_ninja"
73
+ require "binding_of_caller"
74
+
75
+ class Foo
76
+ extend BindingNinja
77
+
78
+ auto_inject_binding def foo1(b)
79
+ b.local_variables
80
+ end
81
+
82
+ def foo2
83
+ binding.of_caller(1).local_variables
84
+ end
85
+
86
+ def foo3(b)
87
+ b.local_variables
88
+ end
89
+ auto_inject_binding :foo3, if: :enable_auto_inject_binding?
90
+
91
+ def enable_auto_inject_binding?
92
+ true
93
+ end
94
+ end
95
+
96
+ foo = Foo.new
97
+
98
+ p foo.foo1
99
+ p foo.foo2
100
+ p foo.foo3
101
+
102
+ Benchmark.ips do |x|
103
+ x.report("binding_ninja") { foo.foo1 }
104
+ x.report("binding_ninja_with_condition") { foo.foo3 }
105
+ x.report("binding_of_caller") { foo.foo2 }
106
+
107
+ x.compare!
108
+ end
109
+ ```
110
+
111
+ ```
112
+ Warming up --------------------------------------
113
+ binding_ninja 106.598k i/100ms
114
+ binding_ninja_with_condition
115
+ 49.660k i/100ms
116
+ binding_of_caller 6.799k i/100ms
117
+ Calculating -------------------------------------
118
+ binding_ninja 1.351M (± 0.4%) i/s - 6.822M in 5.051283s
119
+ binding_ninja_with_condition
120
+ 566.555k (± 0.3%) i/s - 2.880M in 5.083895s
121
+ binding_of_caller 69.968k (± 0.8%) i/s - 353.548k in 5.053337s
122
+
123
+ Comparison:
124
+ binding_ninja: 1350619.1 i/s
125
+ binding_ninja_with_condition: 566555.1 i/s - 2.38x slower
126
+ binding_of_caller: 69968.2 i/s - 19.30x slower
127
+
128
+ ```
129
+
130
+ 13x - 16x faster than binding_of_caller.
131
+ And binding_ninja has very simple code base.
132
+
67
133
  ## Development
68
134
 
69
135
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/benchmark.rb ADDED
@@ -0,0 +1,38 @@
1
+ require "benchmark/ips"
2
+ require "binding_ninja"
3
+ require "binding_of_caller"
4
+
5
+ class Foo
6
+ extend BindingNinja
7
+
8
+ auto_inject_binding def foo1(b)
9
+ b.local_variables
10
+ end
11
+
12
+ def foo2
13
+ binding.of_caller(1).local_variables
14
+ end
15
+
16
+ def foo3(b)
17
+ b.local_variables
18
+ end
19
+ auto_inject_binding :foo3, if: :enable_auto_inject_binding?
20
+
21
+ def enable_auto_inject_binding?
22
+ true
23
+ end
24
+ end
25
+
26
+ foo = Foo.new
27
+
28
+ p foo.foo1
29
+ p foo.foo2
30
+ p foo.foo3
31
+
32
+ Benchmark.ips do |x|
33
+ x.report("binding_ninja") { foo.foo1 }
34
+ x.report("binding_ninja_with_condition") { foo.foo3 }
35
+ x.report("binding_of_caller") { foo.foo2 }
36
+
37
+ x.compare!
38
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  VALUE rb_mBindingNinja;
4
4
  static VALUE auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self);
5
+ static VALUE auto_inject_binding_invoke_without_cond(int argc, VALUE *argv, VALUE self);
6
+ static VALUE auto_inject_binding_invoke_stub(int argc, VALUE *argv, VALUE self);
5
7
 
6
8
  static ID options_id;
7
9
 
@@ -13,6 +15,8 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
13
15
  static ID keyword_ids[1];
14
16
  VALUE extensions, ext_mod, method_sym, options, opt, cond;
15
17
 
18
+ cond = Qundef;
19
+
16
20
  if (!keyword_ids[0]) {
17
21
  keyword_ids[0] = rb_intern("if");
18
22
  }
@@ -21,11 +25,11 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
21
25
  extensions_id = rb_intern("@auto_inject_binding_extensions");
22
26
  }
23
27
 
24
- if (rb_cvar_defined(mod, options_id)) {
25
- options = rb_cvar_get(mod, options_id);
28
+ if (rb_ivar_defined(mod, options_id)) {
29
+ options = rb_ivar_get(mod, options_id);
26
30
  } else {
27
31
  options = rb_hash_new();
28
- rb_cvar_set(mod, options_id, options);
32
+ rb_ivar_set(mod, options_id, options);
29
33
  }
30
34
 
31
35
  rb_scan_args(argc, argv, "1:", &method_sym, &opt);
@@ -51,7 +55,18 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
51
55
  if (rb_mod_include_p(mod, ext_mod) == Qfalse) {
52
56
  rb_prepend_module(mod, ext_mod);
53
57
  }
54
- rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke, -1);
58
+
59
+ if (cond == Qundef) {
60
+ rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke_without_cond, -1);
61
+ } else if (rb_obj_is_proc(cond) || SYMBOL_P(cond)) {
62
+ rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke, -1);
63
+ } else {
64
+ if (RTEST(cond)) {
65
+ rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke_without_cond, -1);
66
+ } else {
67
+ rb_define_method_id(ext_mod, mid, auto_inject_binding_invoke_stub, -1);
68
+ }
69
+ }
55
70
 
56
71
  return method_sym;
57
72
  }
@@ -59,7 +74,7 @@ auto_inject_binding(int argc, VALUE *argv, VALUE mod)
59
74
  static VALUE
60
75
  auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self)
61
76
  {
62
- VALUE method_sym, options, binding, args_ary, cond;
77
+ VALUE method_sym, ext_mod, options, binding, args_ary, cond;
63
78
  static VALUE dummy_proc_args, dummy_method_arg[0];
64
79
 
65
80
  if (!dummy_proc_args) {
@@ -68,7 +83,7 @@ auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self)
68
83
  }
69
84
 
70
85
  method_sym = ID2SYM(rb_frame_this_func());
71
- options = rb_cvar_get(CLASS_OF(self), options_id);
86
+ options = rb_funcall(CLASS_OF(self), rb_intern("auto_inject_binding_options"), 0);
72
87
 
73
88
  cond = rb_hash_lookup2(options, method_sym, Qtrue);
74
89
 
@@ -92,11 +107,31 @@ auto_inject_binding_invoke(int argc, VALUE *argv, VALUE self)
92
107
  return rb_call_super(argc + 1, RARRAY_CONST_PTR(args_ary));
93
108
  }
94
109
 
110
+
111
+ static VALUE
112
+ auto_inject_binding_invoke_without_cond(int argc, VALUE *argv, VALUE self)
113
+ {
114
+ VALUE args_ary, binding;
115
+ args_ary = rb_ary_new_from_values(argc, argv);
116
+ binding = rb_binding_new();
117
+ rb_ary_unshift(args_ary, binding);
118
+ return rb_call_super(argc + 1, RARRAY_CONST_PTR(args_ary));
119
+ }
120
+
121
+ static VALUE
122
+ auto_inject_binding_invoke_stub(int argc, VALUE *argv, VALUE self)
123
+ {
124
+ VALUE args_ary;
125
+ args_ary = rb_ary_new_from_values(argc, argv);
126
+ rb_ary_unshift(args_ary, Qnil);
127
+ return rb_call_super(argc + 1, RARRAY_CONST_PTR(args_ary));
128
+ }
129
+
95
130
  void
96
131
  Init_binding_ninja(void)
97
132
  {
98
133
  rb_mBindingNinja = rb_define_module("BindingNinja");
99
- options_id = rb_intern("@@__auto_inject_binding_options");
134
+ options_id = rb_intern("@auto_inject_binding_options");
100
135
  rb_ivar_set(rb_mBindingNinja, rb_intern("@auto_inject_binding_extensions"), rb_hash_new());
101
136
  rb_define_private_method(rb_mBindingNinja, "auto_inject_binding", auto_inject_binding, -1);
102
137
  }
data/lib/binding_ninja.rb CHANGED
@@ -2,4 +2,34 @@ require "binding_ninja/version"
2
2
  require "binding_ninja/binding_ninja"
3
3
 
4
4
  module BindingNinja
5
+ def auto_inject_binding_options
6
+ {}
7
+ end
8
+
9
+ METHOD_DEFINER = ->(klass) do
10
+ unless klass.method_defined?(:auto_inject_binding_options)
11
+ options = {}
12
+ klass.class_eval do
13
+ @auto_inject_binding_options = options
14
+ end
15
+
16
+ klass.define_singleton_method(:auto_inject_binding_options) do
17
+ super().merge(options)
18
+ end
19
+ end
20
+ end
21
+
22
+ def inherited(klass)
23
+ super
24
+ METHOD_DEFINER.call(klass)
25
+ end
26
+
27
+ def included(klass)
28
+ super
29
+ METHOD_DEFINER.call(klass)
30
+ end
31
+
32
+ def self.extended(klass)
33
+ METHOD_DEFINER.call(klass)
34
+ end
5
35
  end
@@ -1,3 +1,3 @@
1
1
  module BindingNinja
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: binding_ninja
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-24 00:00:00.000000000 Z
11
+ date: 2017-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,7 @@ files:
80
80
  - Gemfile
81
81
  - README.md
82
82
  - Rakefile
83
+ - benchmark.rb
83
84
  - bin/console
84
85
  - bin/setup
85
86
  - binding_ninja.gemspec
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
108
  version: '0'
108
109
  requirements: []
109
110
  rubyforge_project:
110
- rubygems_version: 2.6.12
111
+ rubygems_version: 2.6.13
111
112
  signing_key:
112
113
  specification_version: 4
113
114
  summary: pass binding of method caller implicitly