standard-procedure-signal 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a9695adc72f38352ff51001ae488143a3a793321e9866a9a0d80bbabe0e548a
4
- data.tar.gz: 0c3e7dc3779d7486da4d1ae90a02d85c125e5215356f7278449929215815fd24
3
+ metadata.gz: c347178dc2149032ef830dc559022331c72955415a2bf989e12460a0f3114460
4
+ data.tar.gz: '09db2d1f954710ce4f4eb277dd950f231d93db17ba660d3d95861c7c68bb9c74'
5
5
  SHA512:
6
- metadata.gz: a1d10d456c4c8a6a1dc4d18e9dc9886e75d0fb0eee1468a2402ddb96e0223c1b0d07975afc9b4b002250c2a2c4556bace3406b535c0b4e3e7cc3e58e45b42b30
7
- data.tar.gz: fc21a499e770402d7f5879590fdd50bb3193e3edfeaade891c97c86d79cedc3b879a973703358a94d731a6d185631817fa7998e0a0fdc246a2ddc504730d6207
6
+ metadata.gz: a0ad515217b9f1c5db1c179fb3b0ae9ff7320299e56d1eec1cb038ddd44f2fd31b96d60318af1c39a6a1155764633ebc03d0e2ae6471b0da86ef386fc4e78d0c
7
+ data.tar.gz: 604b0ed2905965347e560071cd171b817f3a75882da9ad81f518f8e86038cb676da1f2263fa07bfda8f7958567ed1a62080d7a2406949cca716392f6446beb40
data/CHANGELOG.md CHANGED
@@ -1,10 +1,11 @@
1
+ ## [0.1.1] - 2023-09-13
2
+
3
+ - Added in [Signal::Attribute::Array](/lib/signal/attribute/array.rb) and [Signal::Attribute::Hash](/lib/signal/attribute/hash.rb)
4
+
1
5
  ## [0.1.0] - 2023-09-08
2
6
 
3
7
  - Initial release
4
8
 
5
9
  Things to do:
6
10
 
7
- - Add proper rspec
8
- - Add in simple types - string, integer, float, date, datetime, boolean
9
- - Add array and hash types
10
11
  - Add compound types
data/README.md CHANGED
@@ -121,48 +121,56 @@ To place a value into an attribute you call `Signal::Attribute#set`, aliased as
121
121
 
122
122
  ### Triggering updates
123
123
 
124
- It's important to note that observables only trigger updates when the `set` method is called with a new value. This has an important implication when it comes to manipulating or mutating values.
124
+ It's important to note that most observables only trigger updates when the `set` method is called with a new value. This means that, in most cases, you cannot _mutate_ a value stored in an observable. Instead, you should replace the value by calling `set`.
125
125
 
126
- For example, if you put a ruby hash into an attribute, the updates will not be triggered if you add or remove keys and values in that hash.
126
+ For example:
127
127
 
128
128
  ```ruby
129
- @attribute = Signal::Attribute.new { key_1: "value_1", key_2: "value_2" }
129
+ # This will not trigger any updates
130
+ @attribute = Signal::Attribute.string "hello"
131
+ @attribute.get.upcase!
130
132
 
131
- # These calls will *not* trigger any updates
132
- @attribute.get[:key_3] = "value_3"
133
- @attribute.get[:key_1] = "some other value"
134
- @attribute.get.transform_values! { |v| v.capitalize }
133
+ # This will trigger updates
134
+ @attribute = Signal::Attribute.string "hello"
135
+ @attribute.set @attribute.get.upcase
135
136
  ```
136
137
 
137
- Instead, you need to manually trigger an update or, better yet, treat the attribute's contents as immutable and replace them.
138
-
139
- Option One: manually triggering updates
140
-
138
+ If necessary, you can manually trigger updates on an observable.
141
139
  ```ruby
142
- @attribute = Signal::Attribute.new { key_1: "value_1", key_2: "value_2" }
143
-
144
- @attribute.get[:key_3] = "value_3"
145
- @attribute.update_observers
146
- @attribute.get[:key_1] = "some other value"
147
- @attribute.update_observers
148
- @attribute.get.transform_values! { |v| v.capitalize }
149
- @attribute.update_observers
140
+ # Manually trigger updates
141
+ @attribute = Signal::Attribute.string "hello"
142
+ @attribute.get.upcase!
143
+ @attribute.update_observers
150
144
  ```
151
145
 
152
- Option Two: treat the data as immutable, copy it then make changes, finally setting the attribute with the new data
153
-
154
- ```ruby
155
- @attribute = Signal::Attribute.new { key_1: "value_1", key_2: "value_2" }
156
-
157
- data = @attribute.get.dup
158
- data[:key_3] = "value_3"
159
- @attribute.set data
146
+ However, there are two mutable attributes that you can use - [Signal::Attribute::Array](/lib/signal/attribute/array.rb) and [Signal::Attribute::Hash](/lib/signal/attribute/hash.rb).
160
147
 
161
- data = @attribute.get.dup
162
- data[:key_1] = "some other value"
163
- @attribute.set data
148
+ These are partial implementations of the ruby Array and Hash classes that are convenience wrappers when it comes to updates. They implement Enumerable, so you can use `each`, `map` and your other favourites, plus they include a subset of the mutation methods to make it easier to manipulate the contents without repeatedly copying, changing and then setting your attributes contents.
164
149
 
165
- @attribute.set(@attribute.get.transform_values { |v| v.capitalize })
150
+ ```ruby
151
+ # Non-mutable array attribute
152
+ @array = [1, 2, 3]
153
+ @attribute = Signal::Attribute.new @array
154
+ @new_array = @array.dup
155
+ @new_array.push 4
156
+ @attribute.set @new_array
157
+
158
+ # Mutable array attribute
159
+ @array = [1, 2, 3]
160
+ @attribute = Signal::Attribute.array @array
161
+ @attribute << 4
162
+
163
+ # Non-mutable hash attribute
164
+ @hash = { key1: "value1", key2: "value2" }
165
+ @attribute = Signal::Attribute.new @hash
166
+ @new_hash = @hash.dup
167
+ @new_hash[:key3] = "value3"
168
+ @attribute.set @new_hash
169
+
170
+ # Mutable hash attribute
171
+ @hash = { key1: "value1", key2: "value2" }
172
+ @attribute = Signal::Attribute.array @hash
173
+ @attribute[:key3] = "value3"
166
174
  ```
167
175
 
168
176
  ## Installation
@@ -0,0 +1 @@
1
+ 87fb50047e2f2b4e14e0a4b48caed00445b344719ca0ea17a8dd82ec92cd48db5ab7a1f1ea87f00da81865045b9f313260b61f34c112f8ba136999a51ae517be
@@ -0,0 +1,51 @@
1
+ module Signal
2
+ class Attribute
3
+ class Array < Attribute
4
+ include Enumerable
5
+
6
+ def set(new_value)
7
+ new_value = if new_value.nil?
8
+ nil
9
+ elsif new_value.respond_to? :map
10
+ new_value.map { |i| Attribute.for i }
11
+ else
12
+ [Attribute.new(new_value)]
13
+ end
14
+ super new_value
15
+ end
16
+
17
+ def push item
18
+ @value.push item
19
+ update_observers
20
+ self
21
+ end
22
+ alias_method :<<, :push
23
+
24
+ def pop
25
+ item = @value.pop
26
+ update_observers
27
+ item
28
+ end
29
+
30
+ def shift
31
+ item = @value.shift
32
+ update_observers
33
+ item
34
+ end
35
+
36
+ def unshift item
37
+ @value.unshift Attribute.for(item)
38
+ update_observers
39
+ self
40
+ end
41
+
42
+ def last
43
+ @value.last
44
+ end
45
+
46
+ def each &block
47
+ @value.each(&block)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,87 @@
1
+ module Signal
2
+ class Attribute
3
+ class Hash < Attribute
4
+ include Enumerable
5
+
6
+ def set(new_value)
7
+ new_value = if new_value.nil?
8
+ nil
9
+ elsif new_value.respond_to? :transform_values
10
+ new_value.transform_values { |value| Attribute.for value }
11
+ else
12
+ raise ArgumentError.new "#{new_value.inspect} is not recognised as a Hash"
13
+ end
14
+ super new_value
15
+ end
16
+
17
+ def each &block
18
+ @value.each(&block)
19
+ end
20
+
21
+ def keys
22
+ @value.keys
23
+ end
24
+
25
+ def include? key
26
+ @value.include? key
27
+ end
28
+
29
+ def has_key? key
30
+ @value.has_key? key
31
+ end
32
+
33
+ def has_value? value, attribute: false
34
+ if attribute
35
+ @value.has_value? value
36
+ else
37
+ @value.values.map(&:get).include? value
38
+ end
39
+ end
40
+
41
+ def values
42
+ @value.values
43
+ end
44
+
45
+ def size
46
+ @value.size
47
+ end
48
+ alias_method :length, :size
49
+
50
+ def any?
51
+ @value.any?
52
+ end
53
+
54
+ def empty?
55
+ @value.empty?
56
+ end
57
+
58
+ def [] key
59
+ @value[key]
60
+ end
61
+
62
+ def fetch key
63
+ @value.fetch key
64
+ end
65
+
66
+ def []= key, value
67
+ @value[key] = value
68
+ update_observers
69
+ end
70
+
71
+ def store key, value
72
+ @value.store key, value
73
+ update_observers
74
+ end
75
+
76
+ def delete key
77
+ @value.delete key
78
+ update_observers
79
+ end
80
+
81
+ def clear
82
+ @value.clear
83
+ update_observers
84
+ end
85
+ end
86
+ end
87
+ end
@@ -15,12 +15,16 @@ module Signal
15
15
  end
16
16
 
17
17
  class << self
18
- %i[text integer float date time boolean].each do |type|
18
+ %i[text integer float date time boolean array hash].each do |type|
19
19
  class_name = "Signal::Attribute::#{type.to_s.capitalize}"
20
20
  define_method type do |value|
21
21
  const_get(class_name).new value
22
22
  end
23
23
  end
24
+
25
+ def for item
26
+ item.is_a?(Signal::Observable) ? item : Attribute.new(item)
27
+ end
24
28
  end
25
29
  end
26
30
  end
@@ -49,7 +49,7 @@ module Signal
49
49
  # The block will be called whenever this signal or its dependents is updated.
50
50
  # The block handler does not require any parameters, simply access the signal, or any other signals and act accordingly. If you access any dependents outside of this signal, they will be tracked and you will be notified again when they update.
51
51
  def observe(&block)
52
- Signal::Manager.observe(&block)
52
+ Signal.observe(&block)
53
53
  end
54
54
 
55
55
  # Notify all observers that this signal has changed
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Signal
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard-procedure-signal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rahoul Baruah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-09-10 00:00:00.000000000 Z
11
+ date: 2023-09-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Observable attributes which adapt based upon their dependencies so we
14
14
  avoid unecessary updates
@@ -29,12 +29,15 @@ files:
29
29
  - README.md
30
30
  - Rakefile
31
31
  - checksums/standard-procedure-signal-0.1.0.gem.sha512
32
+ - checksums/standard-procedure-signal-0.1.1.gem.sha512
32
33
  - lib/signal.rb
33
34
  - lib/signal/attribute.rb
35
+ - lib/signal/attribute/array.rb
34
36
  - lib/signal/attribute/boolean.rb
35
37
  - lib/signal/attribute/date.rb
36
38
  - lib/signal/attribute/float.rb
37
39
  - lib/signal/attribute/format_error.rb
40
+ - lib/signal/attribute/hash.rb
38
41
  - lib/signal/attribute/integer.rb
39
42
  - lib/signal/attribute/text.rb
40
43
  - lib/signal/attribute/time.rb