once-ler 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -0
- data/lib/onceler/basic_helpers.rb +3 -17
- data/lib/onceler/configuration.rb +0 -8
- data/lib/onceler/{blank_tape.rb → recordable.rb} +12 -14
- data/lib/onceler/recorder.rb +8 -36
- metadata +3 -3
data/README.md
CHANGED
@@ -60,6 +60,12 @@ RSpec.configure do |c|
|
|
60
60
|
end
|
61
61
|
```
|
62
62
|
|
63
|
+
## How much of a speedup will I get?
|
64
|
+
|
65
|
+
YMMV, it depends on how bad your `let`s/`before`s are. For example,
|
66
|
+
adding once-ler to a subset of [canvas-lms](https://github.com/instructure/canvas-lms)'s
|
67
|
+
model specs (spec/models/a*) **reduces their runtime by 40%**.
|
68
|
+
|
63
69
|
## How does it work?
|
64
70
|
|
65
71
|
Any `before(:once)`/`let_once` blocks will run just once for the current
|
@@ -76,30 +76,16 @@ module Onceler
|
|
76
76
|
|
77
77
|
def create_onceler!
|
78
78
|
add_onceler_hooks!
|
79
|
-
Recorder.new(
|
79
|
+
Recorder.new(self)
|
80
80
|
end
|
81
81
|
|
82
|
-
# make sure we have access to subsequently added methods when
|
83
|
-
# recording (not just `lets'). note that this really only works
|
84
|
-
# for truly functional methods with no external dependencies. e.g.
|
85
|
-
# methods that add stubs or set instance variables will not work
|
86
|
-
# while recording
|
87
|
-
def method_added(method_name)
|
88
|
-
return if method_name == @current_let_once
|
89
|
-
return if !@onceler
|
90
|
-
proxy = onceler.helper_proxy ||= new
|
91
|
-
onceler.helper_methods[method_name] ||= Proc.new do |*args|
|
92
|
-
proxy.send method_name, *args
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
82
|
def parent_onceler
|
99
83
|
return unless superclass.respond_to?(:onceler)
|
100
84
|
superclass.onceler
|
101
85
|
end
|
102
86
|
|
87
|
+
private
|
88
|
+
|
103
89
|
def add_onceler_hooks!
|
104
90
|
before(:all) do |group|
|
105
91
|
Onceler.configuration.run_callbacks(:record, :before)
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Onceler
|
2
|
-
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
module Recordable
|
3
|
+
def self.extended(instance)
|
4
|
+
instance.instance_eval do
|
5
|
+
@__retvals = {}
|
6
|
+
@__retvals_recorded = {} # we might override an inherited one, so we need to differentiate
|
7
|
+
@__ignore_ivars = instance_variables
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
11
|
def __prepare_recording(recording)
|
@@ -23,10 +25,12 @@ module Onceler
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def __ivars
|
26
|
-
ivars = instance_variables -
|
28
|
+
ivars = instance_variables - @__ignore_ivars
|
27
29
|
ivars.inject({}) do |hash, key|
|
28
|
-
|
29
|
-
|
30
|
+
if key.to_s !~ /\A@__/
|
31
|
+
val = instance_variable_get(key)
|
32
|
+
hash[key] = val
|
33
|
+
end
|
30
34
|
hash
|
31
35
|
end
|
32
36
|
end
|
@@ -35,12 +39,6 @@ module Onceler
|
|
35
39
|
@__data ||= Marshal.dump([__ivars, @__retvals])
|
36
40
|
end
|
37
41
|
|
38
|
-
def copy(mixins)
|
39
|
-
copy = self.class.new(mixins)
|
40
|
-
copy.copy_from(self)
|
41
|
-
copy
|
42
|
-
end
|
43
|
-
|
44
42
|
def copy_from(other)
|
45
43
|
ivars, @__retvals = Marshal.load(other.__data)
|
46
44
|
ivars.each do |key, value|
|
data/lib/onceler/recorder.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "onceler/
|
1
|
+
require "onceler/recordable"
|
2
2
|
require "onceler/transactions"
|
3
3
|
|
4
4
|
module Onceler
|
@@ -7,8 +7,8 @@ module Onceler
|
|
7
7
|
|
8
8
|
attr_accessor :tape, :helper_proxy
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@
|
10
|
+
def initialize(group_class)
|
11
|
+
@group_class = group_class
|
12
12
|
@recordings = []
|
13
13
|
@named_recordings = []
|
14
14
|
end
|
@@ -28,8 +28,11 @@ module Onceler
|
|
28
28
|
|
29
29
|
def record!
|
30
30
|
begin_transactions!
|
31
|
-
@tape = @
|
32
|
-
|
31
|
+
@tape = @group_class.new
|
32
|
+
@tape.send :extend, Recordable
|
33
|
+
if parent = @group_class.parent_onceler
|
34
|
+
@tape.copy_from(parent.tape)
|
35
|
+
end
|
33
36
|
|
34
37
|
# we don't know the order named recordings will be called (or if
|
35
38
|
# they'll call each other), so prep everything first
|
@@ -46,37 +49,6 @@ module Onceler
|
|
46
49
|
rollback_transactions!
|
47
50
|
end
|
48
51
|
|
49
|
-
def proxy_recordable_methods!
|
50
|
-
# the proxy is used to run non-recordable methods that may be called
|
51
|
-
# by ones are recording. since the former could in turn call more of
|
52
|
-
# the latter, we need to proxy the other way too
|
53
|
-
return unless helper_proxy
|
54
|
-
methods = @named_recordings
|
55
|
-
reverse_proxy = @tape
|
56
|
-
helper_proxy.instance_eval do
|
57
|
-
methods.each do |method|
|
58
|
-
define_singleton_method(method) { reverse_proxy.send(method) }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def helper_methods
|
64
|
-
@helper_methods ||= {}
|
65
|
-
end
|
66
|
-
|
67
|
-
def mixins
|
68
|
-
mixins = (@parent ? @parent.mixins : Onceler.configuration.modules).dup
|
69
|
-
if methods = @helper_methods
|
70
|
-
mixin = Module.new do
|
71
|
-
methods.each do |key, method|
|
72
|
-
define_method(key, &method)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
mixins.push mixin
|
76
|
-
end
|
77
|
-
mixins
|
78
|
-
end
|
79
|
-
|
80
52
|
def reconsitute_data!
|
81
53
|
@ivars, @retvals = Marshal.load(@data)
|
82
54
|
identity_map = {}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: once-ler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-06-
|
12
|
+
date: 2014-06-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -54,13 +54,13 @@ files:
|
|
54
54
|
- lib/once-ler.rb
|
55
55
|
- lib/onceler/ambitious_helpers.rb
|
56
56
|
- lib/onceler/basic_helpers.rb
|
57
|
-
- lib/onceler/blank_tape.rb
|
58
57
|
- lib/onceler/configuration.rb
|
59
58
|
- lib/onceler/extensions/active_record.rb
|
60
59
|
- lib/onceler/extensions/active_record_3_0.rb
|
61
60
|
- lib/onceler/extensions/active_record_3_2.rb
|
62
61
|
- lib/onceler/extensions/active_record_4_0.rb
|
63
62
|
- lib/onceler/extensions/active_record_4_1.rb
|
63
|
+
- lib/onceler/recordable.rb
|
64
64
|
- lib/onceler/recorder.rb
|
65
65
|
- lib/onceler/transactions/active_record_3.rb
|
66
66
|
- lib/onceler/transactions/active_record_4.rb
|