opal-shimmer 0.1.2 → 0.2
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 +4 -4
- data/README.md +86 -45
- data/lib/opal/shimmer/version.rb +1 -1
- data/opal-shimmer.gemspec +1 -1
- data/opal/shimmer.rb +2 -1
- data/opal/shimmer/config.rb +19 -0
- data/opal/shimmer/observer.rb +36 -0
- data/spec/observer_spec.rb +109 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1694f4e3a2e7065aa4b9fd21f3769dd112299ea
|
4
|
+
data.tar.gz: 769bb63b91b60ae4d167b8031376d5e40e71e0ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52ce8189f854edf7004589847e62b8ae47bfc094cf0b007707921b9779f5295bc85a7361692eec795aa18368f4dd5219e011d0cd64f32a22fed4f8b4586c57f8
|
7
|
+
data.tar.gz: b7023a2ff7b7f6073bfa8b900b706a52b4e8359caf7345b282d7a29317f14cc4dbd238db025e717c8c1f1694775659691041490c64df870a76ea347178495057
|
data/README.md
CHANGED
@@ -20,52 +20,93 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
Shimmer is very easy to use right out of the box. I'm assuming you'll be using it within the context of a Rails application for this tutorial. Make sure you add `//= require shimmer` to your application.js manifest file.
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
23
|
+
```ruby
|
24
|
+
# Set up the config object:
|
25
|
+
config = Shimmer::Config.new
|
26
|
+
|
27
|
+
# Set some values:
|
28
|
+
config.somevalue = "Wow"
|
29
|
+
config.othervalue = ['This', 'is', 'great!']
|
30
|
+
|
31
|
+
# Get some values:
|
32
|
+
puts config.somevalue # > "Wow"
|
33
|
+
|
34
|
+
# Use namespaces to define very specific values:
|
35
|
+
config.several.levels.deep.stringvalue = "Your string here"
|
36
|
+
puts config.several.levels.deep.stringvalue # > "Your string here"
|
37
|
+
|
38
|
+
# Check whether a value exists:
|
39
|
+
puts config.foo.nil?
|
40
|
+
|
41
|
+
# Set stuff in a namespace using a block:
|
42
|
+
config.really.deep.namespace do |c|
|
43
|
+
c.value1 = 1
|
44
|
+
c.value2 = 2
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
### Persist values across sessions using the browser's localStorage
|
49
|
+
|
50
|
+
Normally when you set and retrieve values in a config object, those values are only stored in-memory, which means when you reload the browser the values are no longer available.
|
51
|
+
|
52
|
+
Shimmer provides a `persist` method that allows you to specify that a value key should be stored in localStorage so that it will be automatically available in a later browser session (or even in the same session if you have a different config instance.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
# Persist values across sessions using localStorage:
|
56
|
+
config.persist(:cease_and_persist)
|
57
|
+
config.cease_and_persist = "abc123"
|
58
|
+
|
59
|
+
config2 = Shimmer::Config.new # this loads up a brand new object
|
60
|
+
config2.persist(:cease_and_persist)
|
61
|
+
|
62
|
+
puts config2.cease_and_persist # > "abc123" Aha! it works!
|
63
|
+
```
|
64
|
+
|
65
|
+
If you want to make sure you don't overwrite previous persisted values by setting default values, there is a `persist_defaults` method available. It creates a special block context where you can set numerous values, and those values will _only_ be set if the values aren't already saved in localStorage. Example:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# An easier way to persist values by setting initial defaults
|
69
|
+
# and not overwriting values that get set differently later:
|
70
|
+
config.persist_defaults do |c|
|
71
|
+
c.somevalue = "abc"
|
72
|
+
c.othervalue = 123
|
73
|
+
end
|
74
|
+
|
75
|
+
# ...user triggers some action...
|
76
|
+
config.somevalue = "xyz"
|
77
|
+
|
78
|
+
# ...days later on a subsquent browser session...
|
79
|
+
puts config.somevalue # > "xyz" not "abc" - Yay!
|
80
|
+
```
|
81
|
+
|
82
|
+
### Use Observers to execute code when config values change
|
83
|
+
|
84
|
+
Shimmer lets you attach an observer (essentially an event handler) to a config object key. The observer will be notified when the value for that key changes, and will receive both the old and the new values as method arguments. Example:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
config = Shimmer::Config.new
|
88
|
+
|
89
|
+
oldval = nil
|
90
|
+
newval = nil
|
91
|
+
|
92
|
+
config.watch do
|
93
|
+
on :somevalue do |new, old|
|
94
|
+
oldval = old
|
95
|
+
newval = new
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
config.somevalue = "Totally cool"
|
100
|
+
|
101
|
+
puts newval # > "Totally cool"
|
102
|
+
|
103
|
+
config.somevalue = "Another cool thing"
|
104
|
+
|
105
|
+
puts newval # > "Another cool thing"
|
106
|
+
puts oldval # > "Totally cool"
|
107
|
+
```
|
67
108
|
|
68
|
-
For more examples, look at the
|
109
|
+
For more examples, look at the `*_spec.rb` files in the `spec` folder.
|
69
110
|
|
70
111
|
## Contributing
|
71
112
|
|
data/lib/opal/shimmer/version.rb
CHANGED
data/opal-shimmer.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "opal-shimmer"
|
8
8
|
spec.version = Opal::Shimmer::VERSION
|
9
9
|
spec.authors = ["Jared White"]
|
10
|
-
spec.email = ["jared@
|
10
|
+
spec.email = ["jared@jaredwhite.com"]
|
11
11
|
spec.description = %q{An application state and configuration management library built with Opal}
|
12
12
|
spec.summary = spec.description
|
13
13
|
spec.homepage = "https://github.com/jaredcwhite/opal-shimmer"
|
data/opal/shimmer.rb
CHANGED
data/opal/shimmer/config.rb
CHANGED
@@ -9,6 +9,7 @@ module Shimmer
|
|
9
9
|
@store = {}
|
10
10
|
@persisted_storage = Shimmer::Storage.new(self)
|
11
11
|
@in_persisting_block = false
|
12
|
+
@observer = Shimmer::Observer.new(self)
|
12
13
|
end
|
13
14
|
|
14
15
|
def parent_level
|
@@ -23,19 +24,28 @@ module Shimmer
|
|
23
24
|
|
24
25
|
if method_name[-1] == "="
|
25
26
|
save_key = method_name[0..-2]
|
27
|
+
|
26
28
|
if @in_persisting_block
|
27
29
|
unless @persisted_storage.should_include?(save_key)
|
28
30
|
@persisted_storage.should_include(save_key)
|
29
31
|
end
|
30
32
|
unless @persisted_storage.include?(save_key)
|
31
33
|
@persisted_storage.save_value(save_key, args[0])
|
34
|
+
@observer.call_watcher(save_key, nil, args[0])
|
35
|
+
else
|
36
|
+
@observer.call_watcher(save_key, nil, @persisted_storage.load_value(save_key))
|
32
37
|
end
|
33
38
|
elsif !@in_persisting_block and @persisted_storage.should_include?(save_key)
|
39
|
+
old_value = @persisted_storage.load_value(save_key)
|
34
40
|
@store[save_key] = args[0]
|
35
41
|
@persisted_storage.save_value(save_key, args[0])
|
42
|
+
@observer.call_watcher(save_key, old_value, @store[save_key])
|
36
43
|
else
|
44
|
+
old_value = @store[save_key]
|
37
45
|
@store[save_key] = args[0]
|
46
|
+
@observer.call_watcher(save_key, old_value, @store[save_key])
|
38
47
|
end
|
48
|
+
|
39
49
|
else
|
40
50
|
if include?(method_name)
|
41
51
|
yield @store[method_name] if block
|
@@ -122,6 +132,15 @@ module Shimmer
|
|
122
132
|
def to_h
|
123
133
|
@store
|
124
134
|
end
|
135
|
+
|
136
|
+
|
137
|
+
### Observer setup
|
138
|
+
def watch(&block)
|
139
|
+
watchdsl = @observer.dsl
|
140
|
+
if block_given?
|
141
|
+
watchdsl.instance_eval(&block)
|
142
|
+
end
|
143
|
+
end
|
125
144
|
end
|
126
145
|
|
127
146
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Shimmer
|
2
|
+
class Observer
|
3
|
+
def initialize(config_object)
|
4
|
+
@config_object = config_object
|
5
|
+
@handlers = {}
|
6
|
+
@dsl = DSL.new(self)
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_watcher(key, block)
|
10
|
+
@handlers[key] = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def call_watcher(key, old, new)
|
14
|
+
if @handlers[key]
|
15
|
+
@handlers[key].call(new, old, @config_object)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def dsl
|
20
|
+
@dsl
|
21
|
+
end
|
22
|
+
|
23
|
+
class DSL
|
24
|
+
def initialize(observer)
|
25
|
+
@observer = observer
|
26
|
+
end
|
27
|
+
def on(key, passed_method=nil, &block)
|
28
|
+
if passed_method
|
29
|
+
@observer.add_watcher(key, passed_method)
|
30
|
+
else
|
31
|
+
@observer.add_watcher(key, block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class CallbackTest
|
4
|
+
attr_accessor :oldval, :newval
|
5
|
+
def initialize
|
6
|
+
self.oldval = "foo"
|
7
|
+
self.newval = "bar"
|
8
|
+
end
|
9
|
+
def check_values(new, old, value_config)
|
10
|
+
self.oldval = old
|
11
|
+
self.newval = new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Shimmer::Observer" do
|
16
|
+
let(:config) { config = Shimmer::Config.new }
|
17
|
+
|
18
|
+
it "can observe stuff" do
|
19
|
+
oldval = "foo"
|
20
|
+
newval = "bar"
|
21
|
+
|
22
|
+
config.watch do
|
23
|
+
on :somevalue do |new, old|
|
24
|
+
oldval = old
|
25
|
+
newval = new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
config.somevalue = "Totally cool"
|
30
|
+
|
31
|
+
expect(oldval).to eq(nil)
|
32
|
+
expect(newval).to eq("Totally cool")
|
33
|
+
end
|
34
|
+
it "can continually observe stuff and access other config values" do
|
35
|
+
oldval = "foo"
|
36
|
+
newval = "bar"
|
37
|
+
|
38
|
+
config.watch do
|
39
|
+
on :somevalue do |new, old, value_config|
|
40
|
+
oldval = "#{value_config.anothervalue} #{old}"
|
41
|
+
newval = "#{new} #{value_config.anothervalue}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
config.anothervalue = 10
|
46
|
+
config.somevalue = "Totally cool"
|
47
|
+
config.somevalue = 543
|
48
|
+
|
49
|
+
expect(oldval).to eq("10 Totally cool")
|
50
|
+
expect(newval).to eq("543 10")
|
51
|
+
|
52
|
+
end
|
53
|
+
it "can call a method of an object as the observer handler" do
|
54
|
+
callback_test = CallbackTest.new
|
55
|
+
|
56
|
+
config.callback_value = "Old stuff"
|
57
|
+
|
58
|
+
config.watch do
|
59
|
+
on :callback_value, callback_test.method(:check_values)
|
60
|
+
end
|
61
|
+
|
62
|
+
config.callback_value = "Totally awesome"
|
63
|
+
|
64
|
+
expect(callback_test.oldval).to eq("Old stuff")
|
65
|
+
expect(callback_test.newval).to eq("Totally awesome")
|
66
|
+
end
|
67
|
+
it "works with persisted items as well" do
|
68
|
+
newval = "foo"
|
69
|
+
oldval = "bar"
|
70
|
+
newsomeval = "foo"
|
71
|
+
oldsomeval = "bar"
|
72
|
+
|
73
|
+
config.watch do
|
74
|
+
on :somevalue do |new, old|
|
75
|
+
newsomeval = new
|
76
|
+
oldsomeval = old
|
77
|
+
end
|
78
|
+
on :othervalue do |new, old|
|
79
|
+
newval = new
|
80
|
+
oldval = old
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
`window.localStorage.removeItem('config.somevalue')`
|
85
|
+
`window.localStorage.removeItem('config.othervalue')`
|
86
|
+
|
87
|
+
`window.localStorage['config.othervalue'] = 321`
|
88
|
+
|
89
|
+
config.persist_defaults do |c|
|
90
|
+
c.somevalue = "abc"
|
91
|
+
c.othervalue = 123
|
92
|
+
end
|
93
|
+
|
94
|
+
expect(oldsomeval).to eq(nil)
|
95
|
+
expect(newsomeval).to eq("abc")
|
96
|
+
|
97
|
+
expect(oldval).to eq(nil)
|
98
|
+
expect(newval).to eq(321)
|
99
|
+
|
100
|
+
config.othervalue = 456
|
101
|
+
config.somevalue = "def"
|
102
|
+
|
103
|
+
expect(oldsomeval).to eq("abc")
|
104
|
+
expect(newsomeval).to eq("def")
|
105
|
+
|
106
|
+
expect(oldval).to eq(321)
|
107
|
+
expect(newval).to eq(456)
|
108
|
+
end
|
109
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-shimmer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jared White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -69,7 +69,7 @@ dependencies:
|
|
69
69
|
description: An application state and configuration management library built with
|
70
70
|
Opal
|
71
71
|
email:
|
72
|
-
- jared@
|
72
|
+
- jared@jaredwhite.com
|
73
73
|
executables: []
|
74
74
|
extensions: []
|
75
75
|
extra_rdoc_files: []
|
@@ -87,8 +87,10 @@ files:
|
|
87
87
|
- opal-shimmer.gemspec
|
88
88
|
- opal/shimmer.rb
|
89
89
|
- opal/shimmer/config.rb
|
90
|
+
- opal/shimmer/observer.rb
|
90
91
|
- opal/shimmer/storage.rb
|
91
92
|
- spec/config_spec.rb
|
93
|
+
- spec/observer_spec.rb
|
92
94
|
- spec/spec_helper.rb
|
93
95
|
- spec/storage_spec.rb
|
94
96
|
homepage: https://github.com/jaredcwhite/opal-shimmer
|
@@ -117,5 +119,6 @@ specification_version: 4
|
|
117
119
|
summary: An application state and configuration management library built with Opal
|
118
120
|
test_files:
|
119
121
|
- spec/config_spec.rb
|
122
|
+
- spec/observer_spec.rb
|
120
123
|
- spec/spec_helper.rb
|
121
124
|
- spec/storage_spec.rb
|