glimmer 2.4.1 → 2.5.4

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: 374a048642d7ade3614c400b3ffefa627d3c40ca6976acf1a7969592865ecef8
4
- data.tar.gz: 5653e8de7ff5ebe9258d872cb72a4067118217e06e698615c9276b95016fb233
3
+ metadata.gz: 8767081e5092e2238c10506725c9b552975128f7b463ec8d6d522a7b763cfcf9
4
+ data.tar.gz: df300e488e8094dc16293e3ab45a06b58a51e6620d3d744040dec2da4bdf09e7
5
5
  SHA512:
6
- metadata.gz: 723e1b9231125f0d3f6507f5312b8a4a12c7bb7e4e3af35cf1f682da317c3a6374d814d0a28e5c2cd37d48255dc3cd7f8e70072b4c0f30bba751ce6730566f45
7
- data.tar.gz: 2449d3783dc09bd4154c62df7ae1d954b0c8c411c98276bfa8ceb4f9d4ac0d1504618614fa33d88afa33b056ba1f04ce8b57050b526aa31ecac36b8954507461
6
+ metadata.gz: 7b9aea718ba6d0e39860bbcf3f24f428dff3e0138ec26244676c9fab419a08a28fc39d4cd9db912b4a224a97016133d79efbf3e8321c4828f5fd66a36ad4b436
7
+ data.tar.gz: 8aa24fa09f117a33b276174c6631d7aecc940ff63346204c65711e2a5e4a064550bd7417d8c9aee4a539b26707c046b4afe7b9f989dea7bf372bb199328539bc
data/CHANGELOG.md CHANGED
@@ -3,6 +3,29 @@
3
3
  Related Change Logs:
4
4
  - [glimmer-dsl-swt/CHANGELOG.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/CHANGELOG.md)
5
5
 
6
+ ### 2.5.4
7
+
8
+ - `Glimmer::DataBinding::ObservableModel` support for observing model attributes with specified `:attribute_writer_type` option (default: `:attribute=`), which can be a single symbol or an array (e.g. `attribute_writer_type: [:attribute=, :set_attribute]`). Glimmer automatches attribute name and automatically generates observer notification attribute writer methods.
9
+
10
+ ### 2.5.3
11
+
12
+ - Provide `Observer#observe` option to tolerate not being able to extend an object for observation by silently not observing such object
13
+ - Use `Concurrent::Hash` for `ObservableModel#property_observer_hash`
14
+ - Use `Concurrent::Hash` for `ObservableHash#key_observer_hash`
15
+
16
+ ### 2.5.1
17
+
18
+ - Fix issue with referencing `OpenStruct` without 'ostruct' library being required (it now checks if `OpenStruct` is loaded first and avoids referencing otherwise).
19
+
20
+ ### 2.5.0
21
+
22
+ - Support observing `Struct`/`OpenStruct` changes via `:[]=` method in addition to attribute writers.
23
+ - Support read-only direct observation of `Hash` object without key via `ModelBinding` (e.g. `ModelBinding.new(some_hash)`)
24
+ - Support read-only direct observation of `Array` object without index via `ModelBinding` (e.g. `ModelBinding.new(some_array)`)
25
+ - Support observing `Hash` attribute with `ModelBinding` (all keys or a single key)
26
+ - Disable `#ensure_hash_object_observer` in ObservableModel/ObservableHash/ObservableArray since it has performance implications and is not necessary
27
+ - Fix issue with `#ensure_array_object_observer` not receiving `recursive: true` option when updating value of an attribute in `ObservableArray`, `ObservableModel`, and `ObservableHash`
28
+
6
29
  ### 2.4.1
7
30
 
8
31
  - Support `recursive: [integer]` option for ObservableArray#add_observer for finite recursion
data/README.md CHANGED
@@ -34,6 +34,7 @@ Start by checking out Glimmer's original GUI DSL, which got extracted into its o
34
34
  - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
35
35
  - [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library)
36
36
  - [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
37
+ - [glimmer-dsl-gtk](https://github.com/AndyObtiva/glimmer-dsl-gtk): Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library)
37
38
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
38
39
  - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
39
40
 
@@ -229,7 +230,7 @@ end
229
230
  ### Setup
230
231
 
231
232
  Follow these steps to author a [Glimmer](https://rubygems.org/gems/glimmer) DSL:
232
- - Add `gem 'glimmer', '~> 2.4.1'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.4.1` and add `require 'glimmer'`
233
+ - Add `gem 'glimmer', '~> 2.5.4'` to `Gemfile` and run `bundle` or run `gem install glimmer -v2.5.4` and add `require 'glimmer'`
233
234
  - Create `glimmer/dsl/[dsl_name]/dsl.rb`, which requires and adds all dynamic expressions for the [dsl_name] Glimmer DSL module as per the code shown in the previous section (or [Official DSLs](#official-dsls) as examples)
234
235
  - Create `glimmer/dsl/[dsl_name]/[expresion_name]_expresion.rb` for every [expresion_name] expression needed, whether dynamic or static
235
236
 
@@ -1184,11 +1185,11 @@ Glimmer enhances observed models automatically (including array operations like
1184
1185
  This relies mainly on the Observer Design Pattern and the MVP (Model-View-Presenter) Architectural Pattern (a variation on MVC)
1185
1186
 
1186
1187
  These are the main classes concerning data-binding:
1187
- - `Glimmer::DataBinding::Observer`: Provides general observer support including unique registration and deregistration for cleanup and prevention of memory leaks. Main methods concerned are: `call`, `register` (alias: `observe`), and `unregister` (alias: `unobserve` or `deregister`)
1188
+ - `Glimmer::DataBinding::Observer`: Provides general observer support including unique registration and deregistration for cleanup and prevention of memory leaks. Main methods concerned are: `call`, `register` (alias: `observe`), and `unregister` (alias: `unobserve` or `deregister`). Passing the option `ignore_frozen: true` at the end of the args of `register` (alias: `observe`) method results in silently ignoring any passed frozen observable without raising an error (it raises an error otherwise for frozen/immutable objects).
1188
1189
  - `Glimmer::DataBinding::Observable`: General super-module for all observables. Main methods concerned are: `add_observer` and `remove_observer`
1189
- - `Glimmer::DataBinding::ObservableModel`: Mixin module for any observable model with observable attributes. In addition to `Observable` methods, it has a `notify_observers` method to be called when changes occur. It automatically enhances all attribute setters (ending with `=`) to notify observers on changes. Also, it automatically handles observing array attributes using `ObservableArray` appropriately so they would notify observers upon array mutation changes.
1190
+ - `Glimmer::DataBinding::ObservableModel`: Mixin module for any observable model (`Object`, `Struct` or `OpenStruct`) with observable attributes (observes attribute writers and `Struct`/`OpenStruct` `:[]=` method). In addition to `Observable` methods, it has a `notify_observers` method to be called when changes occur. It automatically enhances all attribute setters (ending with `=`) to notify observers on changes. Also, it automatically handles observing array attributes using `ObservableArray` appropriately so they would notify observers upon array mutation changes. `:attribute_writer_type` option can be specified (default: `:attribute=`) to observe different attribute styles (e.g. `attribute_writer_type: [:attribute=, :set_attribute]`).
1190
1191
  - `Glimmer::DataBinding::ObservableArray`: Mixin module for any observable array collection that automatically handles notifying observers upon performing array mutation operations (e.g. `push`, `select!`, or `delete`) recursively (meaning if an array contained arrays and they changed, observers are notified). Accepts `recursive: true` option in `add_observer` method to recursively observe nested arrays all the way down. Alternatively, pass `recursive: [integer]` to limit recursion in `Array` observation to a specific number of levels beyond the first level (which is always included).
1191
- - `Glimmer::DataBinding::ObservableHash`: Mixin module for any observable hash that automatically handles notifying observers upon performing hash mutation operations (e.g. `hash[key]=value`, `select!`, `merge!`)
1192
+ - `Glimmer::DataBinding::ObservableHash`: Mixin module for any observable hash that automatically handles notifying observers upon performing hash mutation operations (e.g. `hash[key]=value`, `select!`, `merge!`). Also, it automatically handles observing array values using `ObservableArray` appropriately so they would notify observers upon array mutation changes.
1192
1193
  - `Glimmer::DataBinding::ModelBinding`: a higher-level abstraction that relies on all the other observer/observable classes to support basic data-binding, nested data-binding, and computed data-binding
1193
1194
  - `Glimmer::DataBinding::Shine`: enables highly intuitive and visually expressive syntax to perform bidirectional (two-way) data-binding with `<=>` and unidirectional (one-way) data-binding with `<=`
1194
1195
 
@@ -1254,7 +1255,7 @@ end
1254
1255
 
1255
1256
  Note that if an observed model attribute or hash key is an array, it is automatically observed for array changes, not just attribute/key-value changes.
1256
1257
 
1257
- All of the features above make Glimmer's data-binding library one of the most sophisticated and advanced in the industry since they automate everything instead of requiring endless manual configuration, thus resulting in some of the tersest most declarative syntax for using observers and data-binding.
1258
+ All of the features above make Glimmer's data-binding library one of the most sophisticated and advanced in the industry since it automates everything instead of requiring endless manual configuration, thus resulting in some of the tersest most declarative syntax for using observers and data-binding.
1258
1259
 
1259
1260
  You may learn more by looking into [data-binding specs](/Users/andy/code/glimmer/spec/lib/glimmer/data_binding) as well as [Data-Binding](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#data-binding) and [Observer](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#observer) usage in [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt)
1260
1261
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.4.1
1
+ 2.5.4
data/glimmer.gemspec CHANGED
@@ -1,89 +1,90 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
- # stub: glimmer 2.4.1 ruby lib
6
-
7
- Gem::Specification.new do |s|
8
- s.name = "glimmer".freeze
9
- s.version = "2.4.1"
10
-
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib".freeze]
13
- s.authors = ["AndyMaleh".freeze]
14
- s.date = "2021-11-01"
15
- s.description = "Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of a DSL Engine and an Observable / Observer / Data-Binding Library (including Observable Model, Observable Array, and Observable Hash). Used in Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), Glimmer DSL for Tk (Ruby Desktop Development GUI Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library), Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.".freeze
16
- s.email = "andy.am@gmail.com".freeze
17
- s.extra_rdoc_files = [
18
- "CHANGELOG.md",
19
- "LICENSE.txt",
20
- "README.md"
21
- ]
22
- s.files = [
23
- "CHANGELOG.md",
24
- "CONTRIBUTING.md",
25
- "LICENSE.txt",
26
- "PROCESS.md",
27
- "README.md",
28
- "VERSION",
29
- "glimmer.gemspec",
30
- "lib/glimmer.rb",
31
- "lib/glimmer/config.rb",
32
- "lib/glimmer/data_binding/model_binding.rb",
33
- "lib/glimmer/data_binding/observable.rb",
34
- "lib/glimmer/data_binding/observable_array.rb",
35
- "lib/glimmer/data_binding/observable_hash.rb",
36
- "lib/glimmer/data_binding/observable_model.rb",
37
- "lib/glimmer/data_binding/observer.rb",
38
- "lib/glimmer/data_binding/shine.rb",
39
- "lib/glimmer/dsl/bind_expression.rb",
40
- "lib/glimmer/dsl/engine.rb",
41
- "lib/glimmer/dsl/expression.rb",
42
- "lib/glimmer/dsl/expression_handler.rb",
43
- "lib/glimmer/dsl/observe_expression.rb",
44
- "lib/glimmer/dsl/parent_expression.rb",
45
- "lib/glimmer/dsl/static_expression.rb",
46
- "lib/glimmer/dsl/top_level_expression.rb",
47
- "lib/glimmer/error.rb",
48
- "lib/glimmer/ext/module.rb",
49
- "lib/glimmer/invalid_keyword_error.rb",
50
- "lib/glimmer/shim/concurrent.rb"
51
- ]
52
- s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
53
- s.licenses = ["MIT".freeze]
54
- s.rubygems_version = "3.2.22".freeze
55
- s.summary = "Glimmer - DSL Engine for Ruby GUI and More".freeze
56
-
57
- if s.respond_to? :specification_version then
58
- s.specification_version = 4
59
- end
60
-
61
- if s.respond_to? :add_runtime_dependency then
62
- s.add_runtime_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
63
- s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
64
- s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
65
- s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
66
- s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
67
- s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
68
- s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
69
- s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
70
- s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
71
- s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
72
- s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
73
- s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
74
- else
75
- s.add_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
76
- s.add_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
77
- s.add_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
78
- s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
79
- s.add_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
80
- s.add_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
81
- s.add_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
82
- s.add_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
83
- s.add_dependency(%q<coveralls>.freeze, [">= 0"])
84
- s.add_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
85
- s.add_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
86
- s.add_dependency(%q<rake-tui>.freeze, [">= 0"])
87
- end
88
- end
89
-
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: glimmer 2.5.4 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "glimmer".freeze
9
+ s.version = "2.5.4"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["AndyMaleh".freeze]
14
+ s.date = "2021-12-08"
15
+ s.description = "Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of a DSL Engine and an Observable / Observer / Data-Binding Library (including Observable Model, Observable Array, and Observable Hash). Used in Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), Glimmer DSL for Tk (Ruby Desktop Development GUI Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.".freeze
16
+ s.email = "andy.am@gmail.com".freeze
17
+ s.extra_rdoc_files = [
18
+ "CHANGELOG.md",
19
+ "LICENSE.txt",
20
+ "README.md"
21
+ ]
22
+ s.files = [
23
+ "CHANGELOG.md",
24
+ "CONTRIBUTING.md",
25
+ "LICENSE.txt",
26
+ "PROCESS.md",
27
+ "README.md",
28
+ "VERSION",
29
+ "glimmer.gemspec",
30
+ "lib/glimmer.rb",
31
+ "lib/glimmer/config.rb",
32
+ "lib/glimmer/data_binding/model_binding.rb",
33
+ "lib/glimmer/data_binding/observable.rb",
34
+ "lib/glimmer/data_binding/observable_array.rb",
35
+ "lib/glimmer/data_binding/observable_hash.rb",
36
+ "lib/glimmer/data_binding/observable_hashable.rb",
37
+ "lib/glimmer/data_binding/observable_model.rb",
38
+ "lib/glimmer/data_binding/observer.rb",
39
+ "lib/glimmer/data_binding/shine.rb",
40
+ "lib/glimmer/dsl/bind_expression.rb",
41
+ "lib/glimmer/dsl/engine.rb",
42
+ "lib/glimmer/dsl/expression.rb",
43
+ "lib/glimmer/dsl/expression_handler.rb",
44
+ "lib/glimmer/dsl/observe_expression.rb",
45
+ "lib/glimmer/dsl/parent_expression.rb",
46
+ "lib/glimmer/dsl/static_expression.rb",
47
+ "lib/glimmer/dsl/top_level_expression.rb",
48
+ "lib/glimmer/error.rb",
49
+ "lib/glimmer/ext/module.rb",
50
+ "lib/glimmer/invalid_keyword_error.rb",
51
+ "lib/glimmer/shim/concurrent.rb"
52
+ ]
53
+ s.homepage = "http://github.com/AndyObtiva/glimmer".freeze
54
+ s.licenses = ["MIT".freeze]
55
+ s.rubygems_version = "3.2.22".freeze
56
+ s.summary = "Glimmer - DSL Engine for Ruby GUI and More".freeze
57
+
58
+ if s.respond_to? :specification_version then
59
+ s.specification_version = 4
60
+ end
61
+
62
+ if s.respond_to? :add_runtime_dependency then
63
+ s.add_runtime_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
64
+ s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
65
+ s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
66
+ s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
67
+ s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
68
+ s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
69
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
70
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
71
+ s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
72
+ s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
73
+ s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
74
+ s.add_development_dependency(%q<rake-tui>.freeze, ["> 0"])
75
+ else
76
+ s.add_dependency(%q<array_include_methods>.freeze, ["~> 1.4.0"])
77
+ s.add_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
78
+ s.add_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
79
+ s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
80
+ s.add_dependency(%q<puts_debuggerer>.freeze, ["~> 0.13"])
81
+ s.add_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
82
+ s.add_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
83
+ s.add_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
84
+ s.add_dependency(%q<coveralls>.freeze, [">= 0"])
85
+ s.add_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
86
+ s.add_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
87
+ s.add_dependency(%q<rake-tui>.freeze, ["> 0"])
88
+ end
89
+ end
90
+
@@ -30,9 +30,9 @@ module Glimmer
30
30
 
31
31
  attr_reader :binding_options, :property_name_expression
32
32
 
33
- def initialize(base_model, property_name_expression, binding_options = nil)
34
- @base_model = base_model
35
- @property_name_expression = property_name_expression
33
+ def initialize(*args)
34
+ binding_options = args.pop if args.size > 1 && args.last.is_a?(Hash)
35
+ @base_model, @property_name_expression = args
36
36
  @binding_options = binding_options || Concurrent::Hash.new
37
37
  if computed?
38
38
  @computed_model_bindings = Concurrent::Array.new(computed_by.map do |computed_by_property_expression|
@@ -91,7 +91,7 @@ module Glimmer
91
91
  end
92
92
 
93
93
  def nested_property?
94
- property_name_expression.match(/[.\[]/)
94
+ property_name_expression.to_s.match(/[.\[]/)
95
95
  end
96
96
 
97
97
  def computed?
@@ -137,7 +137,7 @@ module Glimmer
137
137
  apply_processor(@binding_options[:after_read], converted_value)
138
138
  end
139
139
  end
140
- observer_registration = model_binding_observer.observe(model, property_name, observation_options)
140
+ observer_registration = model_binding_observer.observe(*[model, property_name, observation_options].compact)
141
141
  my_registration = observer.registration_for(self)
142
142
  observer.add_dependent(my_registration => observer_registration)
143
143
  end
@@ -206,7 +206,7 @@ module Glimmer
206
206
  def call(value, *extra_args)
207
207
  return if model.nil?
208
208
  converted_value = value
209
- invoke_property_writer(model, "#{property_name}=", converted_value) unless converted_value == evaluate_property
209
+ invoke_property_writer(model, model.is_a?(Hash) ? property_name : "#{property_name}=", converted_value) unless converted_value == evaluate_property || property_name.nil?
210
210
  end
211
211
 
212
212
  def evaluate_property
@@ -263,11 +263,18 @@ module Glimmer
263
263
  property_argument = property_argument.to_i if property_argument.match(/\d+/)
264
264
  object.send(property_method, property_argument)
265
265
  else
266
- object.send(property_expression)
266
+ if property_expression.nil?
267
+ object
268
+ elsif object.is_a?(Hash)
269
+ object[property_expression]
270
+ else
271
+ object.send(property_expression)
272
+ end
267
273
  end
268
274
  end
269
275
 
270
276
  def invoke_property_writer(object, property_expression, value)
277
+ return if property_expression.nil?
271
278
  raise "Cannot invoke `#{property_expression}` because ModelBinding#binding_options[:read_only]=true" if @binding_options[:read_only]
272
279
  apply_processor(@binding_options[:before_write], value)
273
280
  converted_value = convert_on_write(value)
@@ -277,7 +284,11 @@ module Glimmer
277
284
  property_argument = property_argument.to_i if property_argument.match(/\d+/)
278
285
  object.send(property_method, property_argument, converted_value)
279
286
  else
280
- object.send(property_expression, converted_value)
287
+ if object.is_a?(Hash)
288
+ object[property_expression] = converted_value
289
+ else
290
+ object.send(property_expression, converted_value)
291
+ end
281
292
  end
282
293
  apply_processor(@binding_options[:after_write], converted_value)
283
294
  end
@@ -50,8 +50,8 @@ module Glimmer
50
50
  element_properties = args
51
51
  element_properties = element_properties.flatten.compact.uniq
52
52
  return observer if has_observer?(observer) && has_observer_element_properties?(observer, element_properties)
53
- property_observer_list << observer
54
- observer_element_properties[observer] = element_properties_for(observer) + Concurrent::Set.new(element_properties)
53
+ property_observer_list[observer] = options
54
+ observer_element_properties[observer] = Concurrent::Set.new(Concurrent::Array.new(element_properties_for(observer).to_a) + Concurrent::Array.new(element_properties)) # converting to Array as a workaround to jruby-9.3.2.0 issue TODO remove this workaround when no longer needed
55
55
  if !options.empty? && options[:recursive].is_a?(Integer)
56
56
  options = options.clone
57
57
  options[:recursive] = options[:recursive] - 1
@@ -60,9 +60,9 @@ module Glimmer
60
60
  observer
61
61
  end
62
62
 
63
- def add_element_observers(element, options = {})
64
- property_observer_list.each do |observer|
65
- add_element_observer(element, observer, options)
63
+ def add_element_observers(element, general_options = {})
64
+ property_observer_list.each do |observer, options|
65
+ add_element_observer(element, observer, options.merge(general_options))
66
66
  end
67
67
  end
68
68
 
@@ -79,7 +79,7 @@ module Glimmer
79
79
  return unless object&.is_a?(Array)
80
80
  array_object_observer = array_object_observer_for(object)
81
81
  array_observer_registration = array_object_observer.observe(object, options)
82
- property_observer_list.each do |observer|
82
+ property_observer_list.each do |observer, options|
83
83
  my_registration = observer.registration_for(self)
84
84
  observer.add_dependent(my_registration => array_observer_registration)
85
85
  end
@@ -97,7 +97,7 @@ module Glimmer
97
97
  element_properties = element_properties.flatten.compact.uniq
98
98
  if !element_properties.empty?
99
99
  old_element_properties = element_properties_for(observer)
100
- observer_element_properties[observer] = element_properties_for(observer) - Concurrent::Set.new(element_properties)
100
+ observer_element_properties[observer] = Concurrent::Set.new(Concurrent::Array.new(element_properties_for(observer).to_a) - Concurrent::Array.new(element_properties)) # TODO remove this workaround when no longer needed (it is for jruby-9.3.2.0 issue)
101
101
  each { |element| element_properties.each { |property| observer.unobserve(element, property) } }
102
102
  end
103
103
  if element_properties_for(observer).empty?
@@ -109,7 +109,7 @@ module Glimmer
109
109
  end
110
110
 
111
111
  def remove_element_observers(element)
112
- property_observer_list.each do |observer|
112
+ property_observer_list.each do |observer, options|
113
113
  remove_element_observer(element, observer)
114
114
  end
115
115
  end
@@ -120,15 +120,15 @@ module Glimmer
120
120
  end
121
121
  if element.is_a?(ObservableArray)
122
122
  array_object_observer_for(element).unobserve(element)
123
- element.property_observer_list.select {|o| o.respond_to?(:observable_array) && o.observable_array == self}.each do |o|
124
- o.deregister_all_observables
123
+ element.property_observer_list.select {|obs, opt| obs.respond_to?(:observable_array) && obs.observable_array == self}.each do |o|
124
+ o.deregister_all_observables if o.respond_to?(:deregister_all_observables)
125
125
  @array_object_observers.reject! {|k, v| v == o}
126
126
  end
127
127
  end
128
128
  end
129
129
 
130
130
  def has_observer?(observer)
131
- property_observer_list.include?(observer)
131
+ property_observer_list.keys.include?(observer)
132
132
  end
133
133
 
134
134
  def has_observer_element_properties?(observer, element_properties)
@@ -136,7 +136,7 @@ module Glimmer
136
136
  end
137
137
 
138
138
  def property_observer_list
139
- @property_observer_list ||= Concurrent::Set.new
139
+ @property_observer_list ||= Concurrent::Hash.new
140
140
  end
141
141
 
142
142
  def observer_element_properties
@@ -148,7 +148,7 @@ module Glimmer
148
148
  end
149
149
 
150
150
  def notify_observers
151
- property_observer_list.to_a.each { |o| o.call(self) }
151
+ property_observer_list.to_a.each { |obs, opt| obs.call(self) }
152
152
  end
153
153
 
154
154
  def <<(element)
@@ -372,7 +372,7 @@ module Glimmer
372
372
 
373
373
  def unregister_dependent_observers(old_value)
374
374
  return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray)
375
- property_observer_list.each { |observer| observer.unregister_dependents_with_observable(observer.registration_for(self), old_value) }
375
+ property_observer_list.each { |observer, options| observer.unregister_dependents_with_observable(observer.registration_for(self), old_value) }
376
376
  end
377
377
  alias deregister_dependent_observers unregister_dependent_observers
378
378
  end
@@ -19,13 +19,13 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
- require 'glimmer/data_binding/observable'
22
+ require 'glimmer/data_binding/observable_hashable'
23
23
  require 'glimmer/data_binding/observer'
24
24
 
25
25
  module Glimmer
26
26
  module DataBinding
27
27
  module ObservableHash
28
- include Observable
28
+ include ObservableHashable
29
29
 
30
30
  class Notifier
31
31
  include Observer
@@ -40,28 +40,6 @@ module Glimmer
40
40
  end
41
41
  end
42
42
 
43
- OBSERVED_STORE_METHOD = lambda do |key, value|
44
- if key_observer_list(key).empty?
45
- if all_key_observer_list.empty?
46
- self.send('__original__store', key, value)
47
- else
48
- old_value = self[key]
49
- unregister_dependent_observers(nil, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer
50
- self.send('__original__store', key, value)
51
- notify_observers(key)
52
- ensure_array_object_observer(nil, value, old_value)
53
- ensure_hash_object_observer(nil, value, old_value)
54
- end
55
- else
56
- old_value = self[key]
57
- unregister_dependent_observers(key, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer
58
- self.send('__original__store', key, value)
59
- notify_observers(key)
60
- ensure_array_object_observer(key, value, old_value)
61
- ensure_hash_object_observer(key, value, old_value)
62
- end
63
- end
64
-
65
43
  def add_observer(observer, key = nil, options = {})
66
44
  if key.is_a?(Hash)
67
45
  options = key
@@ -106,7 +84,7 @@ module Glimmer
106
84
  end
107
85
 
108
86
  def key_observer_hash
109
- @key_observers ||= Hash.new
87
+ @key_observers ||= Concurrent::Hash.new
110
88
  end
111
89
 
112
90
  def key_observer_list(key)
@@ -123,24 +101,6 @@ module Glimmer
123
101
  (key_observer_list(key).to_a - all_key_observer_list.to_a).each { |observer| observer.call(self[key], key) }
124
102
  end
125
103
 
126
- def add_key_writer_observer(key = nil, options)
127
- ensure_array_object_observer(key, self[key], nil, options)
128
- ensure_hash_object_observer(key, self[key], nil, options)
129
- begin
130
- method('__original__store')
131
- rescue
132
- define_singleton_method('__original__store', store_method)
133
- define_singleton_method('[]=', &OBSERVED_STORE_METHOD)
134
- end
135
- rescue => e
136
- #ignore writing if no key writer exists
137
- Glimmer::Config.logger.debug {"No need to observe store method: '[]='\n#{e.message}\n#{e.backtrace.join("\n")}"}
138
- end
139
-
140
- def store_method
141
- self.class.instance_method('[]=') rescue self.method('[]=')
142
- end
143
-
144
104
  def unregister_dependent_observers(key, old_value)
145
105
  # TODO look into optimizing this
146
106
  return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray) || old_value.is_a?(ObservableHash)
@@ -166,24 +126,6 @@ module Glimmer
166
126
  @array_object_observers[key]
167
127
  end
168
128
 
169
- def ensure_hash_object_observer(key, object, old_object = nil, options = {})
170
- options ||= {}
171
- return unless object&.is_a?(Hash)
172
- hash_object_observer = hash_object_observer_for(key)
173
- hash_observer_registration = hash_object_observer.observe(object, options)
174
- key_observer_list(key).each do |observer|
175
- my_registration = observer.registration_for(self, key) # TODO eliminate repetition
176
- observer.add_dependent(my_registration => hash_observer_registration)
177
- end
178
- hash_object_observer_for(key).unregister(old_object) if old_object.is_a?(ObservableHash)
179
- end
180
-
181
- def hash_object_observer_for(key)
182
- @hash_object_observers ||= Concurrent::Hash.new
183
- @hash_object_observers[key] = ObservableModel::Notifier.new(self, key) unless @hash_object_observers.has_key?(key)
184
- @hash_object_observers[key]
185
- end
186
-
187
129
  def delete(key, &block)
188
130
  old_value = self[key]
189
131
  unless old_value.nil?
@@ -0,0 +1,75 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/data_binding/observable'
23
+
24
+ module Glimmer
25
+ module DataBinding
26
+ # Represents a Hash-like object with attributes writable via :[]= store method like Hash, Struct, and OpenStruct
27
+ # Expects including class to have the following methods:
28
+ # - key_observer_list
29
+ # - all_key_observer_list
30
+ # - unregister_dependent_observer
31
+ # - ensure_array_object_observer
32
+ module ObservableHashable
33
+ include Observable
34
+
35
+ OBSERVED_STORE_METHOD = lambda do |options|
36
+ lambda do |key, value|
37
+ if key_observer_list(key).empty?
38
+ if all_key_observer_list.empty?
39
+ self.send('__original__store', key, value)
40
+ else
41
+ old_value = self[key]
42
+ unregister_dependent_observers(nil, old_value) # remove dependent observers previously installed in ensure_array_object_observer
43
+ self.send('__original__store', key, value)
44
+ notify_observers(key)
45
+ ensure_array_object_observer(nil, value, old_value, options)
46
+ end
47
+ else
48
+ old_value = self[key]
49
+ unregister_dependent_observers(key, old_value) # remove dependent observers previously installed in ensure_array_object_observer
50
+ self.send('__original__store', key, value)
51
+ notify_observers(key)
52
+ ensure_array_object_observer(key, value, old_value, options)
53
+ end
54
+ end
55
+ end
56
+
57
+ def add_key_writer_observer(key = nil, options)
58
+ ensure_array_object_observer(key, self[key], nil, options)
59
+ begin
60
+ method('__original__store')
61
+ rescue
62
+ define_singleton_method('__original__store', store_method)
63
+ define_singleton_method('[]=', &OBSERVED_STORE_METHOD.call(options))
64
+ end
65
+ rescue => e
66
+ #ignore writing if no key writer exists
67
+ Glimmer::Config.logger.debug {"No need to observe store method: '[]='\n#{e.message}\n#{e.backtrace.join("\n")}"}
68
+ end
69
+
70
+ def store_method
71
+ self.class.instance_method('[]=') rescue self.method('[]=')
72
+ end
73
+ end
74
+ end
75
+ end
@@ -19,13 +19,13 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
- require 'glimmer/data_binding/observable'
22
+ require 'glimmer/data_binding/observable_hashable'
23
23
  require 'glimmer/data_binding/observer'
24
24
 
25
25
  module Glimmer
26
26
  module DataBinding
27
27
  module ObservableModel
28
- include Observable
28
+ include ObservableHashable
29
29
 
30
30
  class Notifier
31
31
  include Observer
@@ -40,25 +40,26 @@ module Glimmer
40
40
  end
41
41
  end
42
42
 
43
- PROPERTY_WRITER_FACTORY = lambda do |property_name|
44
- property_writer_name = "#{property_name}="
43
+ PROPERTY_WRITER_FACTORY = lambda do |property_name, property_writer_name, options|
45
44
  lambda do |value|
46
45
  old_value = self.send(property_name)
47
- unregister_dependent_observers(property_name, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer
46
+ unregister_dependent_observers(property_name, old_value) # remove dependent observers previously installed in ensure_array_object_observer
48
47
  self.send("__original__#{property_writer_name}", value)
49
48
  notify_observers(property_name)
50
- ensure_array_object_observer(property_name, value, old_value)
51
- ensure_hash_object_observer(property_name, value, old_value)
49
+ ensure_array_object_observer(property_name, value, old_value, options)
52
50
  end
53
51
  end
54
-
52
+
55
53
  def add_observer(observer, property_name, options = {})
54
+ initialize_observer_options(options)
56
55
  return observer if has_observer?(observer, property_name)
57
56
  property_observer_list(property_name) << observer
58
57
  add_property_writer_observers(property_name, options)
58
+ open_struct_loaded = !!::OpenStruct rescue false
59
+ add_key_writer_observer(property_name, options) if is_a?(Struct) || (open_struct_loaded && is_a?(OpenStruct))
59
60
  observer
60
61
  end
61
-
62
+
62
63
  def remove_observer(observer, property_name, options = {})
63
64
  if has_observer?(observer, property_name)
64
65
  property_observer_list(property_name).delete(observer)
@@ -67,10 +68,11 @@ module Glimmer
67
68
  end
68
69
 
69
70
  def remove_observers(property_name)
70
- property_observer_hash[property_name.to_sym].each do |observer|
71
+ property_key = property_name&.to_sym
72
+ property_observer_hash[property_key].each do |observer|
71
73
  remove_observer(observer, property_name)
72
74
  end
73
- property_observer_hash.delete(property_name.to_sym)
75
+ property_observer_hash.delete(property_key)
74
76
  end
75
77
 
76
78
  def remove_all_observers
@@ -91,32 +93,44 @@ module Glimmer
91
93
  end
92
94
 
93
95
  def property_observer_hash
94
- @property_observers ||= Hash.new
96
+ @property_observers ||= Concurrent::Hash.new
95
97
  end
96
98
 
97
99
  def property_observer_list(property_name)
98
- property_observer_hash[property_name.to_sym] = Concurrent::Set.new unless property_observer_hash[property_name.to_sym]
99
- property_observer_hash[property_name.to_sym]
100
+ property_key = property_name&.to_sym
101
+ property_observer_hash[property_key] = Concurrent::Set.new unless property_observer_hash[property_key]
102
+ property_observer_hash[property_key]
100
103
  end
104
+ alias key_observer_list property_observer_list
105
+
106
+ def all_property_observer_list
107
+ property_observer_list(nil)
108
+ end
109
+ alias all_key_observer_list all_property_observer_list
101
110
 
102
111
  def notify_observers(property_name)
103
112
  property_observer_list(property_name).to_a.each { |observer| observer.call(send(property_name)) }
104
113
  end
105
-
114
+
106
115
  def add_property_writer_observers(property_name, options)
107
- property_writer_name = "#{property_name}="
108
- method(property_writer_name)
109
- ensure_array_object_observer(property_name, send(property_name), nil, options)
110
- ensure_hash_object_observer(property_name, send(property_name), nil, options)
111
- begin
112
- method("__original__#{property_writer_name}")
113
- rescue
114
- define_singleton_method("__original__#{property_writer_name}", property_writer_method(property_writer_name))
115
- define_singleton_method(property_writer_name, &PROPERTY_WRITER_FACTORY.call(property_name))
116
+ options[:attribute_writer_type].each do |attribute_writer_type|
117
+ begin
118
+ property_writer_name = attribute_writer_type.to_s.gsub('attribute', property_name.to_s)
119
+ method(property_writer_name)
120
+ ensure_array_object_observer(property_name, send(property_name), nil, options)
121
+ begin
122
+ method("__original__#{property_writer_name}")
123
+ rescue
124
+ define_singleton_method("__original__#{property_writer_name}", property_writer_method(property_writer_name))
125
+ # Note the limitation that the first observe call options apply to all subsequent observations meaning even if unobserve was called, options do not change from initial ones
126
+ # It is good enough for now. If there is a need to address this in the future, this is where to start the work
127
+ define_singleton_method(property_writer_name, &PROPERTY_WRITER_FACTORY.call(property_name, property_writer_name, options))
128
+ end
129
+ rescue => e
130
+ #ignore writing if no property writer exists
131
+ Glimmer::Config.logger.debug {"No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"}
132
+ end
116
133
  end
117
- rescue => e
118
- #ignore writing if no property writer exists
119
- Glimmer::Config.logger.debug {"No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"}
120
134
  end
121
135
 
122
136
  def property_writer_method(property_writer_name)
@@ -130,7 +144,7 @@ module Glimmer
130
144
  end
131
145
  alias deregister_dependent_observers unregister_dependent_observers
132
146
 
133
- def ensure_array_object_observer(property_name, object, old_object = nil, options = {})
147
+ def ensure_array_object_observer(property_name, object, old_object = nil, options = nil)
134
148
  options ||= {}
135
149
  return unless object&.is_a?(Array)
136
150
  array_object_observer = array_object_observer_for(property_name)
@@ -147,23 +161,10 @@ module Glimmer
147
161
  @array_object_observers[property_name] = Notifier.new(self, property_name) unless @array_object_observers.has_key?(property_name)
148
162
  @array_object_observers[property_name]
149
163
  end
150
-
151
- def ensure_hash_object_observer(property_name, object, old_object = nil, options)
152
- options ||= {}
153
- return unless object&.is_a?(Hash)
154
- hash_object_observer = hash_object_observer_for(property_name)
155
- hash_observer_registration = hash_object_observer.observe(object, options)
156
- property_observer_list(property_name).each do |observer|
157
- my_registration = observer.registration_for(self, property_name) # TODO eliminate repetition
158
- observer.add_dependent(my_registration => hash_observer_registration)
159
- end
160
- hash_object_observer_for(property_name).unregister(old_object) if old_object.is_a?(ObservableHash)
161
- end
162
164
 
163
- def hash_object_observer_for(property_name)
164
- @hash_object_observers ||= Concurrent::Hash.new
165
- @hash_object_observers[property_name] = Notifier.new(self, property_name) unless @hash_object_observers.has_key?(property_name)
166
- @hash_object_observers[property_name]
165
+ def initialize_observer_options(options)
166
+ options[:attribute_writer_type] ||= [:attribute=]
167
+ options[:attribute_writer_type] = [options[:attribute_writer_type]] if !options[:attribute_writer_type].is_a?(Array)
167
168
  end
168
169
  end
169
170
  end
@@ -47,11 +47,11 @@ module Glimmer
47
47
  end
48
48
 
49
49
  class Registration < Struct.new(:observer, :observable, :args, keyword_init: true)
50
- def unregister
50
+ def deregister
51
51
  observer.unobserve(observable, *args)
52
52
  end
53
- alias unobserve unregister
54
- alias deregister unregister
53
+ alias unregister deregister
54
+ alias unobserve deregister
55
55
  end
56
56
 
57
57
  class << self
@@ -82,8 +82,10 @@ module Glimmer
82
82
 
83
83
  # registers observer in an observable on args usually containing a property and options (optional)
84
84
  # observer maintains registration list to unregister later
85
- def register(observable, *args)
85
+ def observe(observable, *args)
86
+ options = args.last.is_a?(Hash) ? args.last : {}
86
87
  return if observable.nil?
88
+ return if options[:ignore_frozen] && observable.frozen?
87
89
  unless observable.is_a?(Observable)
88
90
  # TODO refactor code to be more smart/polymorphic/automated and honor open/closed principle (e.g. for SomeClass, search if there is ObservableSomeClass)
89
91
  if observable.is_a?(Array)
@@ -98,9 +100,9 @@ module Glimmer
98
100
  observable.add_observer(self, *args)
99
101
  ensure_registration_for!(observable, *args)
100
102
  end
101
- alias observe register
103
+ alias register observe
102
104
 
103
- def unregister(observable, *args)
105
+ def unobserve(observable, *args)
104
106
  return unless observable.is_a?(Observable)
105
107
  args = compact_args(args)
106
108
  registration = registration_for(observable, *args)
@@ -113,27 +115,27 @@ module Glimmer
113
115
  observable.remove_observer(self, *args)
114
116
  end
115
117
  end
116
- alias unobserve unregister
117
- alias deregister unregister
118
+ alias unregister unobserve
119
+ alias deregister unobserve
118
120
 
119
- def unregister_dependents_with_observable(registration, dependent_observable)
121
+ def unobserve_dependents_with_observable(registration, dependent_observable)
120
122
  thedependents = dependents_for(registration).select do |thedependent|
121
123
  thedependent.observable == dependent_observable
122
124
  end
123
125
  thedependents.each(&:deregister)
124
126
  end
125
- alias unobserve_dependents_with_observable unregister_dependents_with_observable
126
- alias deregister_dependents_with_observable unregister_dependents_with_observable
127
+ alias unregister_dependents_with_observable unobserve_dependents_with_observable
128
+ alias deregister_dependents_with_observable unobserve_dependents_with_observable
127
129
 
128
130
  # cleans up all registrations in observables
129
- def unregister_all_observables
131
+ def unobserve_all_observables
130
132
  registrations.values.dup.each do |registration|
131
133
  registration.deregister
132
134
  registrations.delete([registration.observable.object_id, registration.args])
133
135
  end
134
136
  end
135
- alias unobserve_all_observables unregister_all_observables
136
- alias deregister_all_observables unregister_all_observables
137
+ alias unregister_all_observables unobserve_all_observables
138
+ alias deregister_all_observables unobserve_all_observables
137
139
 
138
140
  # add dependent observer to unregister when unregistering observer
139
141
  def add_dependent(parent_to_dependent_hash)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-01 00:00:00.000000000 Z
11
+ date: 2021-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: array_include_methods
@@ -192,23 +192,24 @@ dependencies:
192
192
  name: rake-tui
193
193
  requirement: !ruby/object:Gem::Requirement
194
194
  requirements:
195
- - - ">="
195
+ - - ">"
196
196
  - !ruby/object:Gem::Version
197
197
  version: '0'
198
198
  type: :development
199
199
  prerelease: false
200
200
  version_requirements: !ruby/object:Gem::Requirement
201
201
  requirements:
202
- - - ">="
202
+ - - ">"
203
203
  - !ruby/object:Gem::Version
204
204
  version: '0'
205
205
  description: Glimmer is a Ruby DSL Framework for Ruby GUI and More, consisting of
206
206
  a DSL Engine and an Observable / Observer / Data-Binding Library (including Observable
207
207
  Model, Observable Array, and Observable Hash). Used in Glimmer DSL for SWT (JRuby
208
- Desktop Development GUI Framework), Glimmer DSL for Tk (Ruby Desktop Development
209
- GUI Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development
210
- GUI Library), Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop
211
- Apps), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS.
208
+ Desktop Development GUI Framework), Glimmer DSL for Opal (Pure Ruby Web GUI and
209
+ Auto-Webifier of Desktop Apps), Glimmer DSL for Tk (Ruby Desktop Development GUI
210
+ Library), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI
211
+ Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer
212
+ DSL for XML (& HTML), and Glimmer DSL for CSS.
212
213
  email: andy.am@gmail.com
213
214
  executables: []
214
215
  extensions: []
@@ -230,6 +231,7 @@ files:
230
231
  - lib/glimmer/data_binding/observable.rb
231
232
  - lib/glimmer/data_binding/observable_array.rb
232
233
  - lib/glimmer/data_binding/observable_hash.rb
234
+ - lib/glimmer/data_binding/observable_hashable.rb
233
235
  - lib/glimmer/data_binding/observable_model.rb
234
236
  - lib/glimmer/data_binding/observer.rb
235
237
  - lib/glimmer/data_binding/shine.rb