Module: Onceler::Recordable

Defined in:
lib/onceler/recordable.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(instance) ⇒ Object



3
4
5
6
7
8
9
# File 'lib/onceler/recordable.rb', line 3

def self.extended(instance)
  instance.instance_eval do
    @__retvals = {}
    @__inherited_retvals = {}
    @__ignore_ivars = instance_variables
  end
end

Instance Method Details

#__data(inherit = false) ⇒ Object



56
57
58
59
# File 'lib/onceler/recordable.rb', line 56

def __data(inherit = false)
  @__data ||= {}
  @__data[inherit] ||= Marshal.dump([__ivars(inherit), __retvals(inherit)])
end

#__ivars(inherit = false) ⇒ Object



34
35
36
37
38
39
40
41
42
43
# File 'lib/onceler/recordable.rb', line 34

def __ivars(inherit = false)
  ivars = instance_variables - @__ignore_ivars
  ivars.inject({}) do |hash, key|
    if key.to_s !~ /\A@__/
      val = instance_variable_get(key)
      hash[key] = val if __mutated?(key, val) || inherit
    end
    hash
  end
end

#__mutated?(key, val) ⇒ Boolean

we don’t include inherited stuff in __data, because we might need to interleave things from an intermediate before(:each) at run time

Returns:

  • (Boolean)


47
48
49
50
51
52
53
54
# File 'lib/onceler/recordable.rb', line 47

def __mutated?(key, val)
  return true unless @__inherited_cache
  # need to do both types of comparison, i.e. it's the same object in
  # memory (not reassigned), and nothing about it has been changed
  return false if @__inherited_values.equal?(val)
  return false if @__inherited_cache[key] == val
  true
end

#__prepare_recording(recording) ⇒ Object



11
12
13
14
15
16
17
18
19
20
# File 'lib/onceler/recordable.rb', line 11

def __prepare_recording(recording)
  method = recording.name
  define_singleton_method(method) do
    if @__retvals.key?(method)
      @__retvals[method]
    else
      @__retvals[method] = __record(recording)
    end
  end
end

#__record(recording) ⇒ Object



22
23
24
# File 'lib/onceler/recordable.rb', line 22

def __record(recording)
  instance_eval(&recording.block)
end

#__retvals(inherit = false) ⇒ Object



26
27
28
29
30
31
32
# File 'lib/onceler/recordable.rb', line 26

def __retvals(inherit = false)
  retvals = @__inherited_retvals.merge(@__retvals)
  retvals.inject({}) do |hash, (key, val)|
    hash[key] = val if __mutated?(key, val) || inherit
    hash
  end
end

#copy_from(other) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/onceler/recordable.rb', line 61

def copy_from(other)
  # need two copies of things for __mutated? checks (see above)
  @__inherited_cache = Marshal.load(other.__data(:inherit)).inject(&:merge)
  ivars, retvals = Marshal.load(other.__data(:inherit))
  @__inherited_retvals = retvals
  @__inherited_values = ivars.merge(retvals)
  ivars.each do |key, value|
    instance_variable_set(key, value)
  end
  retvals.each do |key, value|
    define_singleton_method(key) { value }
  end
end