opal-shimmer 0.1.2 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|