rbdux 0.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 +7 -0
- data/lib/rbdux/action.rb +66 -0
- data/lib/rbdux/middleware/dispatch_interceptor.rb +13 -0
- data/lib/rbdux/store.rb +166 -0
- data/lib/rbdux.rb +3 -0
- metadata +47 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1e2b52fe3fdf03fb4b57e8875edf152dfa7dba39
|
4
|
+
data.tar.gz: 2a4cdd6c7dd86694bac2dee6af8fddeb793bdbed
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7bbe51b93c102910fac95498117eff8774c924448bcb3b7e7308b8cf5f204f605321eb4bccc6c0cf2d1835d0674872cd1e6c1b20f64e6e16a7f38919d53f9b7a
|
7
|
+
data.tar.gz: 0b81e094159550b1bad1fe2508471abf88c9fb7a350c8ba2230f6c52320cca4e351f8b1bc61a836f918a2f5338dab073ba3fe612e00abacc80fb3f2d52559b0d
|
data/lib/rbdux/action.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Rbdux
|
2
|
+
class Action
|
3
|
+
class << self
|
4
|
+
def define(type_name, &block)
|
5
|
+
klass_name = "#{prepare_action_name(type_name)}Action"
|
6
|
+
|
7
|
+
return Object.const_get(klass_name) if Object.const_defined? klass_name
|
8
|
+
|
9
|
+
Object.const_set(klass_name, build_action_type(block))
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
class BaseAction
|
15
|
+
class << self
|
16
|
+
attr_reader :dispatch_func
|
17
|
+
|
18
|
+
def empty
|
19
|
+
new(nil, nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_payload(payload)
|
23
|
+
new(payload, nil)
|
24
|
+
end
|
25
|
+
|
26
|
+
def with_error(error)
|
27
|
+
new(nil, error)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :payload, :error
|
32
|
+
|
33
|
+
def error?
|
34
|
+
!error.nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def initialize(payload, error)
|
40
|
+
@payload = payload
|
41
|
+
@error = error
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def prepare_action_name(name)
|
46
|
+
camelize_action_name(name.tr('-', '_')).gsub('Action', '')
|
47
|
+
end
|
48
|
+
|
49
|
+
def camelize_action_name(name)
|
50
|
+
name.split('_').collect { |n| capitalize(n) }.join
|
51
|
+
end
|
52
|
+
|
53
|
+
def capitalize(name)
|
54
|
+
name_array = name.split('')
|
55
|
+
name_array.first.upcase!
|
56
|
+
name_array.join
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_action_type(func)
|
60
|
+
Class.new(BaseAction) do
|
61
|
+
@dispatch_func = func
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/rbdux/store.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Rbdux
|
4
|
+
class Store
|
5
|
+
class << self
|
6
|
+
@instance = nil
|
7
|
+
|
8
|
+
def instance
|
9
|
+
@instance ||= Store.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset
|
13
|
+
@instance = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_state(state)
|
17
|
+
@instance = Store.new(state)
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(method, *args, &block)
|
21
|
+
return unless instance.respond_to?(method)
|
22
|
+
|
23
|
+
@instance.send(method, *args, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :state
|
28
|
+
|
29
|
+
def reduce(action, state_key = nil, &block)
|
30
|
+
add_reducer(action, state_key, true, block)
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def reduce_and_merge(action, state_key = nil, &block)
|
36
|
+
add_reducer(action, state_key, false, block)
|
37
|
+
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def when_merging(&block)
|
42
|
+
validate_functional_inputs(block)
|
43
|
+
|
44
|
+
@merge_func = block
|
45
|
+
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def before(&block)
|
50
|
+
@before_middleware << block if block
|
51
|
+
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def after(&block)
|
56
|
+
@after_middleware << block if block
|
57
|
+
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def dispatch(action)
|
62
|
+
previous_state = state
|
63
|
+
|
64
|
+
dispatched_action = apply_before_middleware(action)
|
65
|
+
|
66
|
+
reducers.fetch(action.class.name, []).each do |reducer|
|
67
|
+
apply_reducer!(reducer, dispatched_action)
|
68
|
+
end
|
69
|
+
|
70
|
+
apply_after_middleware(previous_state, dispatched_action)
|
71
|
+
|
72
|
+
observers.values.each(&:call)
|
73
|
+
end
|
74
|
+
|
75
|
+
def subscribe(&block)
|
76
|
+
validate_functional_inputs(block)
|
77
|
+
|
78
|
+
subscriber_id = SecureRandom.uuid
|
79
|
+
|
80
|
+
observers[subscriber_id] = block
|
81
|
+
|
82
|
+
subscriber_id
|
83
|
+
end
|
84
|
+
|
85
|
+
def unsubscribe(subscriber_id)
|
86
|
+
observers.delete(subscriber_id)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
Reducer = Struct.new(:state_key, :auto_merge, :func)
|
92
|
+
|
93
|
+
attr_reader :observers, :reducers
|
94
|
+
|
95
|
+
def initialize(state = {})
|
96
|
+
@state = state
|
97
|
+
@observers = {}
|
98
|
+
@reducers = {}
|
99
|
+
@before_middleware = []
|
100
|
+
@after_middleware = []
|
101
|
+
@merge_func = nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_reducer(action, state_key, auto_merge, func)
|
105
|
+
validate_functional_inputs(func)
|
106
|
+
|
107
|
+
key = action.name
|
108
|
+
|
109
|
+
reducers[key] = [] unless reducers.key?(key)
|
110
|
+
reducers[key] << Reducer.new(state_key, auto_merge, func)
|
111
|
+
end
|
112
|
+
|
113
|
+
def apply_before_middleware(action)
|
114
|
+
dispatched_action = action
|
115
|
+
|
116
|
+
@before_middleware.each do |m|
|
117
|
+
new_action = m.call(self, dispatched_action)
|
118
|
+
dispatched_action = new_action unless new_action.nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
dispatched_action
|
122
|
+
end
|
123
|
+
|
124
|
+
def apply_after_middleware(previous_state, action)
|
125
|
+
@after_middleware.each do |m|
|
126
|
+
m.call(previous_state, state, action)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def apply_reducer!(reducer, action)
|
131
|
+
reducer_params = [slice_state(reducer.state_key), action]
|
132
|
+
reducer_params << state unless reducer.auto_merge
|
133
|
+
new_state = reducer.func.call(*reducer_params)
|
134
|
+
|
135
|
+
return if new_state.nil?
|
136
|
+
|
137
|
+
@state = if reducer.auto_merge
|
138
|
+
merge_state(new_state, reducer.state_key)
|
139
|
+
else
|
140
|
+
new_state
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def slice_state(state_key)
|
145
|
+
return state unless state_key
|
146
|
+
|
147
|
+
state[state_key]
|
148
|
+
end
|
149
|
+
|
150
|
+
def merge_state(new_state, state_key)
|
151
|
+
if @merge_func.nil?
|
152
|
+
default_merge(state, new_state, state_key)
|
153
|
+
else
|
154
|
+
@merge_func.call(state, new_state, state_key)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def default_merge(old_state, new_state, state_key)
|
159
|
+
old_state.dup.merge(state_key ? { state_key => new_state } : new_state)
|
160
|
+
end
|
161
|
+
|
162
|
+
def validate_functional_inputs(block)
|
163
|
+
raise ArgumentError, 'You must define a block.' unless block
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/lib/rbdux.rb
ADDED
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rbdux
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Tompkins
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-02 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: josh@joshtompkins.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/rbdux.rb
|
20
|
+
- lib/rbdux/action.rb
|
21
|
+
- lib/rbdux/middleware/dispatch_interceptor.rb
|
22
|
+
- lib/rbdux/store.rb
|
23
|
+
homepage: https://github.com/jtompkins/rbdux
|
24
|
+
licenses:
|
25
|
+
- MIT
|
26
|
+
metadata: {}
|
27
|
+
post_install_message:
|
28
|
+
rdoc_options: []
|
29
|
+
require_paths:
|
30
|
+
- lib
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 2.5.1
|
44
|
+
signing_key:
|
45
|
+
specification_version: 4
|
46
|
+
summary: A simple one-way dataflow library, inspired by Redux
|
47
|
+
test_files: []
|