binding_ninja 0.2.0 → 0.2.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.
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