hyper-store 0.99.6 → 1.0.alpha1

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.
@@ -0,0 +1,116 @@
1
+ module Hyperstack
2
+ module Internal
3
+ module Store
4
+ class StateWrapper < BaseStoreClass
5
+ extend ArgumentValidator
6
+
7
+ class << self
8
+ attr_reader :instance_state_wrapper, :class_state_wrapper,
9
+ :instance_mutator_wrapper, :class_mutator_wrapper,
10
+ :wrappers
11
+
12
+ def inherited(subclass)
13
+ subclass.add_class_instance_vars(subclass) if self == StateWrapper
14
+ end
15
+
16
+ def add_class_instance_vars(subclass)
17
+ @shared_state_wrapper = subclass
18
+ @instance_state_wrapper = Class.new(@shared_state_wrapper)
19
+ @class_state_wrapper = Class.new(@shared_state_wrapper)
20
+
21
+ @shared_mutator_wrapper = Class.new(MutatorWrapper)
22
+ @instance_mutator_wrapper = Class.new(@shared_mutator_wrapper)
23
+ @class_mutator_wrapper = Class.new(@shared_mutator_wrapper)
24
+
25
+ @wrappers = [@instance_state_wrapper, @instance_mutator_wrapper,
26
+ @class_state_wrapper, @class_mutator_wrapper]
27
+ end
28
+
29
+ def define_state_methods(klass, *args, &block)
30
+ return self if args.empty?
31
+
32
+ name, opts = validate_args!(klass, *args, &block)
33
+
34
+ add_readers(klass, name, opts)
35
+ klass.singleton_class.state.add_error_methods(name, opts)
36
+ klass.singleton_class.state.add_methods(klass, name, opts)
37
+ klass.singleton_class.state.remove_methods(name, opts)
38
+ klass.send(:"__#{opts[:scope]}_states") << [name, opts]
39
+ end
40
+
41
+ def add_readers(klass, name, opts)
42
+ return unless opts[:reader]
43
+
44
+ if [:instance, :shared].include?(opts[:scope])
45
+ klass.class_eval do
46
+ define_method(:"#{opts[:reader]}") { state.__send__(:"#{name}") }
47
+ end
48
+ end
49
+
50
+ if [:class, :shared].include?(opts[:scope])
51
+ klass.define_singleton_method(:"#{opts[:reader]}") { state.__send__(:"#{name}") }
52
+ end
53
+ end
54
+
55
+ def add_error_methods(name, opts)
56
+ return if opts[:scope] == :shared
57
+
58
+ [@shared_state_wrapper, @shared_mutator_wrapper].each do |klass|
59
+ klass.define_singleton_method(:"#{name}") do
60
+ 'nope!'
61
+ end
62
+ end
63
+ end
64
+
65
+ def add_methods(klass, name, opts)
66
+ instance_variable_get("@#{opts[:scope]}_state_wrapper").add_method(klass, name, opts)
67
+ instance_variable_get("@#{opts[:scope]}_mutator_wrapper").add_method(klass, name, opts)
68
+ end
69
+
70
+ def add_method(klass, method_name, opts = {})
71
+ define_method(:"#{method_name}") do
72
+ from = opts[:scope] == :shared ? klass.state.__from__ : @__from__
73
+ from.init_store if from.respond_to? :init_store
74
+ State.get_state(from, method_name.to_s)
75
+ end
76
+ end
77
+
78
+ def remove_methods(name, opts)
79
+ return unless opts[:scope] == :shared
80
+
81
+ wrappers.each do |wrapper|
82
+ wrapper.send(:remove_method, :"#{name}") if wrapper.respond_to?(:"#{name}")
83
+ end
84
+ end
85
+
86
+ def default_scope(klass)
87
+ if self == klass.singleton_class.__state_wrapper.class_state_wrapper
88
+ :instance
89
+ else
90
+ :class
91
+ end
92
+ end
93
+ end
94
+
95
+ attr_accessor :__from__
96
+
97
+ def self.new(from)
98
+ instance = allocate
99
+ instance.__from__ = from
100
+ instance
101
+ end
102
+
103
+ def [](name)
104
+ __send__(name)
105
+ end
106
+
107
+ # Any method_missing call will create a state and accessor with that name
108
+ def method_missing(name, *args, &block) # rubocop:disable Style/MethodMissing
109
+ $method_missing = [name, *args]
110
+ (class << self; self end).add_method(nil, name) #(class << self; self end).superclass.add_method(nil, name)
111
+ __send__(name, *args, &block)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,93 @@
1
+ module Hyperstack
2
+ module Internal
3
+ module Store
4
+ class StateWrapper < BaseStoreClass
5
+ module ArgumentValidator
6
+ def validate_args!(klass, *args, &block)
7
+ name, initial_value, opts = parse_arguments(*args, &block)
8
+
9
+ opts[:scope] ||= default_scope(klass)
10
+ opts[:initializer] = validate_initializer(initial_value, klass, opts)
11
+ opts[:block] = block if block
12
+
13
+ if opts[:reader]
14
+ opts[:reader] = opts[:reader] == true ? name : opts[:reader]
15
+ end
16
+
17
+ [name, opts]
18
+ end
19
+
20
+ private
21
+
22
+ def invalid_option(message)
23
+ raise Legacy::Store::InvalidOptionError, message
24
+ end
25
+
26
+ # Parses the arguments given to get the name, initial_value (if any), and options
27
+ def parse_arguments(*args)
28
+ # If the only argument is a hash, the first key => value is name => inital_value
29
+ if args.first.is_a?(Hash)
30
+ # If the first key passed in is not the name, raise an error
31
+ if [:reader, :initializer, :scope].include?(args.first.keys.first.to_sym)
32
+ message = 'The name of the state must be specified first as '\
33
+ "either 'state :name' or 'state name: nil'"
34
+ invalid_option(message)
35
+ end
36
+
37
+ name, initial_value = args[0].shift
38
+ # Otherwise just the name is passed in by itself first
39
+ else
40
+ name = args.shift
41
+ end
42
+
43
+ # [name, initial_value (can be nil), args (if nil then return an empty hash)]
44
+ [name, initial_value, args[0] || {}]
45
+ end
46
+
47
+ # Converts the initialize option to a Proc
48
+ def validate_initializer(initial_value, klass, opts) # rubocop:disable Metrics/MethodLength
49
+ # If we pass in the name as a hash with a value ex: state foo: :bar,
50
+ # we just put that value inside a Proc and return that
51
+ if initial_value != nil
52
+ dup_or_return_intial_value(initial_value)
53
+ # If we pass in the initialize option
54
+ elsif opts[:initializer]
55
+ # If it's a Symbol we convert to to a Proc that calls the method on the instance
56
+ if [Symbol, String].include?(opts[:initializer].class)
57
+ method_name = opts[:initializer]
58
+ if [:class, :shared].include?(opts[:scope])
59
+ -> { klass.send(:"#{method_name}") }
60
+ else
61
+ ->(instance) { instance.send(:"#{method_name}") }
62
+ end
63
+ # If it is already a Proc we do nothing and just return what was given
64
+ elsif opts[:initializer].is_a?(Proc)
65
+ opts[:initializer]
66
+ # If it's not a Proc or a String we raise an error and return an empty Proc
67
+ else
68
+ invalid_option("'state' option 'initialize' must either be a Symbol or a Proc")
69
+ -> {}
70
+ end
71
+ # Otherwise if it's not specified we just return an empty Proc
72
+ else
73
+ -> {}
74
+ end
75
+ end
76
+
77
+ # Dup the initial value if possible, otherwise just return it
78
+ # Ruby has no nice way of doing this...
79
+ def dup_or_return_intial_value(value)
80
+ value =
81
+ begin
82
+ value.dup
83
+ rescue
84
+ value
85
+ end
86
+
87
+ -> { value }
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,23 @@
1
+ module Hyperstack
2
+ module Legacy
3
+ module Store
4
+ class InvalidOptionError < StandardError; end
5
+ class InvalidOperationError < StandardError; end
6
+ class << self
7
+ def included(base)
8
+ base.include(Hyperstack::Internal::Store::InstanceMethods)
9
+ base.extend(Hyperstack::Internal::Store::ClassMethods)
10
+ base.extend(Hyperstack::Internal::Store::DispatchReceiver)
11
+
12
+ base.singleton_class.define_singleton_method(:__state_wrapper) do
13
+ @__state_wrapper ||= Class.new(Hyperstack::Internal::Store::StateWrapper)
14
+ end
15
+
16
+ base.singleton_class.define_singleton_method(:state) do |*args, &block|
17
+ __state_wrapper.define_state_methods(base, *args, &block)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ module Hyperstack
2
+ module Legacy
3
+ module Store
4
+ VERSION = '1.0.alpha1'
5
+ end
6
+ end
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyper-store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.99.6
4
+ version: 1.0.alpha1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mitch VanDuyn
@@ -10,22 +10,36 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2019-01-30 00:00:00.000000000 Z
13
+ date: 2018-11-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: hyperloop-config
16
+ name: hyperstack-config
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.99.6
21
+ version: 1.0.alpha1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '='
27
27
  - !ruby/object:Gem::Version
28
- version: 0.99.6
28
+ version: 1.0.alpha1
29
+ - !ruby/object:Gem::Dependency
30
+ name: hyper-state
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '='
34
+ - !ruby/object:Gem::Version
35
+ version: 1.0.alpha1
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '='
41
+ - !ruby/object:Gem::Version
42
+ version: 1.0.alpha1
29
43
  - !ruby/object:Gem::Dependency
30
44
  name: opal
31
45
  requirement: !ruby/object:Gem::Requirement
@@ -80,28 +94,28 @@ dependencies:
80
94
  requirements:
81
95
  - - '='
82
96
  - !ruby/object:Gem::Version
83
- version: 0.99.6
97
+ version: 1.0.alpha1
84
98
  type: :development
85
99
  prerelease: false
86
100
  version_requirements: !ruby/object:Gem::Requirement
87
101
  requirements:
88
102
  - - '='
89
103
  - !ruby/object:Gem::Version
90
- version: 0.99.6
104
+ version: 1.0.alpha1
91
105
  - !ruby/object:Gem::Dependency
92
106
  name: hyper-spec
93
107
  requirement: !ruby/object:Gem::Requirement
94
108
  requirements:
95
109
  - - '='
96
110
  - !ruby/object:Gem::Version
97
- version: 0.99.6
111
+ version: 1.0.alpha1
98
112
  type: :development
99
113
  prerelease: false
100
114
  version_requirements: !ruby/object:Gem::Requirement
101
115
  requirements:
102
116
  - - '='
103
117
  - !ruby/object:Gem::Version
104
- version: 0.99.6
118
+ version: 1.0.alpha1
105
119
  - !ruby/object:Gem::Dependency
106
120
  name: listen
107
121
  requirement: !ruby/object:Gem::Requirement
@@ -122,14 +136,14 @@ dependencies:
122
136
  requirements:
123
137
  - - "~>"
124
138
  - !ruby/object:Gem::Version
125
- version: 0.2.4
139
+ version: 0.1.15
126
140
  type: :development
127
141
  prerelease: false
128
142
  version_requirements: !ruby/object:Gem::Requirement
129
143
  requirements:
130
144
  - - "~>"
131
145
  - !ruby/object:Gem::Version
132
- version: 0.2.4
146
+ version: 0.1.15
133
147
  - !ruby/object:Gem::Dependency
134
148
  name: opal-browser
135
149
  requirement: !ruby/object:Gem::Requirement
@@ -172,6 +186,20 @@ dependencies:
172
186
  - - ">="
173
187
  - !ruby/object:Gem::Version
174
188
  version: '0'
189
+ - !ruby/object:Gem::Dependency
190
+ name: pry-rescue
191
+ requirement: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ type: :development
197
+ prerelease: false
198
+ version_requirements: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
175
203
  - !ruby/object:Gem::Dependency
176
204
  name: puma
177
205
  requirement: !ruby/object:Gem::Requirement
@@ -248,6 +276,20 @@ dependencies:
248
276
  - - "~>"
249
277
  - !ruby/object:Gem::Version
250
278
  version: 3.7.0
279
+ - !ruby/object:Gem::Dependency
280
+ name: rspec-rails
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
251
293
  - !ruby/object:Gem::Dependency
252
294
  name: rspec-steps
253
295
  requirement: !ruby/object:Gem::Requirement
@@ -290,6 +332,20 @@ dependencies:
290
332
  - - ">="
291
333
  - !ruby/object:Gem::Version
292
334
  version: '0'
335
+ - !ruby/object:Gem::Dependency
336
+ name: timecop
337
+ requirement: !ruby/object:Gem::Requirement
338
+ requirements:
339
+ - - "~>"
340
+ - !ruby/object:Gem::Version
341
+ version: 0.8.1
342
+ type: :development
343
+ prerelease: false
344
+ version_requirements: !ruby/object:Gem::Requirement
345
+ requirements:
346
+ - - "~>"
347
+ - !ruby/object:Gem::Version
348
+ version: 0.8.1
293
349
  description:
294
350
  email:
295
351
  - mitch@catprint.com
@@ -300,26 +356,22 @@ extra_rdoc_files: []
300
356
  files:
301
357
  - ".gitignore"
302
358
  - ".travis.yml"
303
- - DOCS.md
304
359
  - Gemfile
305
- - README.md
306
360
  - Rakefile
307
361
  - bin/console
308
362
  - bin/setup
309
363
  - hyper-store.gemspec
310
364
  - lib/hyper-store.rb
311
- - lib/hyper-store/class_methods.rb
312
- - lib/hyper-store/dispatch_receiver.rb
313
- - lib/hyper-store/instance_methods.rb
314
- - lib/hyper-store/mutator_wrapper.rb
315
- - lib/hyper-store/state_wrapper.rb
316
- - lib/hyper-store/state_wrapper/argument_validator.rb
317
- - lib/hyper-store/version.rb
318
- - lib/hyperloop/application/boot.rb
319
- - lib/hyperloop/store.rb
320
- - lib/hyperloop/store/mixin.rb
321
- - lib/react/observable.rb
322
- - lib/react/state.rb
365
+ - lib/hyperstack/internal/store/class_methods.rb
366
+ - lib/hyperstack/internal/store/dispatch_receiver.rb
367
+ - lib/hyperstack/internal/store/instance_methods.rb
368
+ - lib/hyperstack/internal/store/mutator_wrapper.rb
369
+ - lib/hyperstack/internal/store/observable.rb
370
+ - lib/hyperstack/internal/store/state.rb
371
+ - lib/hyperstack/internal/store/state_wrapper.rb
372
+ - lib/hyperstack/internal/store/state_wrapper/argument_validator.rb
373
+ - lib/hyperstack/legacy/store.rb
374
+ - lib/hyperstack/legacy/store/version.rb
323
375
  homepage: https://ruby-hyperloop.org
324
376
  licenses:
325
377
  - MIT
@@ -335,11 +387,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
335
387
  version: '0'
336
388
  required_rubygems_version: !ruby/object:Gem::Requirement
337
389
  requirements:
338
- - - ">="
390
+ - - ">"
339
391
  - !ruby/object:Gem::Version
340
- version: '0'
392
+ version: 1.3.1
341
393
  requirements: []
342
- rubygems_version: 3.0.2
394
+ rubyforge_project:
395
+ rubygems_version: 2.7.8
343
396
  signing_key:
344
397
  specification_version: 4
345
398
  summary: Flux Stores and more for Hyperloop