Skip to content
This repository was archived by the owner on Oct 19, 2018. It is now read-only.

Commit 6052cd4

Browse files
committed
updated state handling sketch
1 parent 79d58d5 commit 6052cd4

File tree

1 file changed

+84
-33
lines changed

1 file changed

+84
-33
lines changed

lib/hyper-store/state_example.rb

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,91 @@
1-
class State
1+
class StateWrapper
22
class << self
33
def inherited(subclass)
4-
return unless self == State
5-
@shared_proxy = subclass
6-
@instance_proxy = Class.new(@shared_proxy)
7-
@class_proxy = Class.new(@shared_proxy)
8-
@shared_mutator_proxy = Class.new(Mutator)
9-
@instance_mutator_proxy = Class.new(@shared_mutator_proxy)
10-
@class_mutator_proxy = Class.new(@shared_mutator_proxy)
4+
subclass.add_class_instance_vars if self == StateWrapper
115
end
126

13-
attr_reader :instance_proxy
14-
attr_reader :class_proxy
15-
attr_reader :instance_mutator_proxy
16-
attr_reader :class_mutator_proxy
7+
def add_class_instance_vars
8+
@shared_state_wrapper = subclass
9+
@instance_state_wrapper = Class.new(@shared_wrapper)
10+
@class_state_wrapper = Class.new(@shared_wrapper)
11+
@shared_mutator_wrapper = Class.new(Mutator)
12+
@instance_mutator_wrapper = Class.new(@shared_mutator_wrapper)
13+
@class_mutator_wrapper = Class.new(@shared_mutator_wrapper)
14+
@wrappers = [
15+
@instance_state_wrapper, @instance_mutator_wrapper,
16+
@class_state_wrapper, @class_mutator_wrapper
17+
]
1718

18-
def define_accessor(*args, &block)
19-
# process args into name, opts, and init_value
20-
# call add_error_methods / add_method / remove_method
2119
end
2220

23-
def add_error_methods name
24-
[@shared_proxy, @shared_mutator_proxy].each do |klass|
25-
klass.define_method(name) do |*args, &block|
21+
attr_reader :instance_state_wrapper
22+
attr_reader :class_state_wrapper
23+
attr_reader :instance_mutator_wrapper
24+
attr_reader :class_mutator_wrapper
25+
attr_reader :wrappers
26+
27+
def define_state_methods(klass, *args, &block)
28+
return self if args.empty?
29+
opts = process_args(klass, *args)
30+
add_readers(klass, opts)
31+
add_error_methods(opts)
32+
add_methods(opts)
33+
remove_methods(opts)
34+
end
35+
36+
def process_args(klass, *args, &block)
37+
# returns *args processed into opts, will add name key, and will update initialize key
38+
# and the scope
39+
# so that initialize is always a proc or nil... that part if fun
40+
# (state_name: some_value...) ==+> (name: :state_name, initialize: -> () { some_value.dup })
41+
# (state_name, ... initialize: :meth_name) ===> (name: :state_name, initialize: klass-depends-on-scope.method(:meth_name))
42+
# (state_name, ... initialize: someproc) ===> (name: :state_name, initialize: someproc)
43+
# (state_name, ... &block) ===> (name: :state_name, initialize: block)
44+
# (state_name ....) ===> (name: :state_name, ... no initialize key ...)
45+
end
46+
47+
def add_readers(klass, opts)
48+
if opts[:scope] == :instance
49+
klass.define_method(opts[:reader]) { state.send(opts[:name]) } ## we could get it directly from React::State...
50+
else
51+
klass.singleton_class.define_method(...) I think???
52+
end unless opts[:reader]
53+
end
54+
55+
def add_error_methods(opts)
56+
[@shared_state_wrapper, @shared_mutator_wrapper].each do |klass|
57+
klass.define_method(opts[:name]) do |*args, &block|
2658
"illegal boss"
2759
end
28-
end
60+
end unless opts[:scope] == :shared
61+
end
62+
63+
def add_methods(opts)
64+
instance_variable_get("@#{opts[:scope]}_state_wrapper").add_method opts[:name], opts[:initialize], opts[:reader]
65+
instance_variable_get("@#{opts[:scope]}_mutator_wrapper").add_method opts[:name]
2966
end
3067

31-
def add_method(name, opts = {}, init_value, &block)
32-
define_method(name) do ...
68+
def remove_methods(opts)
69+
wrappers.each { |wrapper| wrapper.remove_method opts[:name] } if opts[:scope] == :shared
70+
end
71+
72+
def add_method(klass, opts)
73+
# define the method
74+
define_method(opts[:name]) do ...
3375
end
76+
77+
return unless opts[:initializer]
3478
end
3579

3680
def default_scope
37-
self == @instance_proxy ? :instance : :class
81+
# remember:
82+
# class Store
83+
# state :foo # this is calling the state wrapper but defining instance variables
84+
# class << self
85+
# state :foo # this is calling the shared state wrapper but defining class variables
86+
# end
87+
# end
88+
self == @class_state_wrapper ? :instance : :class
3889
end
3990
end
4091

@@ -45,7 +96,7 @@ def method_missing(name, *args, &block)
4596

4697
end
4798

48-
class Mutator
99+
class MutatorWrapper
49100
def method_missing(name, *args, &block)
50101
self.class.add_method name
51102
self.send(name, *args, &block)
@@ -60,28 +111,28 @@ def define_method(name) do ...
60111
class HyperStore::Base
61112
def self.inherited(child)
62113
child.singleton_class.define_singleton_method(:state) do |*args, &block|
63-
@state ||= Class.new(State).new
64-
@state.class.define_accessor(*args, &block)
65-
@state
114+
# the singleton_class_method is only called either to define states
115+
# or for the class and instance methods to get the wrapper so we just
116+
# save the wrapper. We don't need an instance here.
117+
@state_wrapper ||= Class.new(StateWrapper)
118+
@state_wrapper.define_state_methods(child, *args, &block) # i think this is self here
66119
end
67120
end
68121

69122
def self.state(*args, &block)
70-
@state ||= singleton_class.state.class.class_proxy.new
71-
singleton_class.state.class.class_proxy.process_args(*args, &block)
72-
@state
123+
singleton_class.state.class_state_wrapper.define_state_methods(child, *args, &block)
124+
@state ||= singleton_class.state.class_state_wrapper.new
73125
end
74126

75127
def self.mutate
76-
@mutate ||= singleton_class.state.class.class_mutator_proxy.new
128+
@mutate ||= singleton_class.state.class_mutator_wrapper.new
77129
end
78130

79131
def state
80-
@state ||= self.class.singleton_class.state.class.instance_proxy.new
132+
@state ||= self.class.singleton_class.instance_state_wrapper.new
81133
end
82134

83135
def mutate
84-
@mutate ||= self.class.singleton_class.state.class.instance_mutator_proxy.new
136+
@mutate ||= self.class.singleton_class.instance_mutator_wrapper.new
85137
end
86-
87138
end

0 commit comments

Comments
 (0)