opal-shimmer 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: af6a671a4a06532b0934e407682744bdbef4da6f
4
+ data.tar.gz: 919e18ae911f83b2e07794b649d5d4b44bb81461
5
+ SHA512:
6
+ metadata.gz: b831db064daa0baf27102cb59bda9796b3f5d5f3046f6766c57956f7f888747b2b42243cc6363b1a0547ebcb35069249a8733cb938af62705a2ff6952d7a63d6
7
+ data.tar.gz: 9958ef8839dcb23deb1880ded1c0e4dc023d8462b1d192eb3708207b04ca02e4f011a540415131c10723b7eb8cb8b317c95ba1b3215faf10f3c6a56fec64b003
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1 @@
1
+ ruby-2.1.2@ruby2rails4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in opal-shimmer.gemspec
4
+ gemspec
5
+
6
+ gem 'opal-rspec'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014-2015 Jared White
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,82 @@
1
+ # Opal: Shimmer
2
+
3
+ Shimmer is an application state and configuration management library built with [Opal](http://opalrb.org), a Ruby-to-JS compiler.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'opal-shimmer'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install opal-shimmer
18
+
19
+ ## Usage
20
+
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
+
23
+ # Set up the config object:
24
+ config = Shimmer::Config.new
25
+
26
+ # Set some values:
27
+ config.somevalue = "Wow"
28
+ config.othervalue = ['This', 'is', 'great!']
29
+
30
+ # Get some values:
31
+ puts config.somevalue # > "Wow"
32
+
33
+ # Use namespaces to define very specific values:
34
+ config.several.levels.deep.stringvalue = "Your string here"
35
+ puts config.several.levels.deep.stringvalue # > "Your string here"
36
+
37
+ # Check whether a value exists:
38
+ puts config.foo.nil?
39
+
40
+ # Set stuff in a namespace using a block:
41
+ config.really.deep.namespace do |c|
42
+ c.value1 = 1
43
+ c.value2 = 2
44
+ end
45
+
46
+ # Persist values across sessions using localStorage:
47
+ config.persist(:cease_and_persist)
48
+ config.cease_and_persist = "abc123"
49
+
50
+ config2 = Shimmer::Config.new # this loads up a brand new object
51
+ config2.persist(:cease_and_persist)
52
+
53
+ puts config2.cease_and_persist # > "abc123" Aha! it works!
54
+
55
+ # An easier way to persist values by setting initial defaults
56
+ # and not overwriting values that get set differently later:
57
+ config.persist_defaults do |c|
58
+ c.somevalue = "abc"
59
+ c.othervalue = 123
60
+ end
61
+
62
+ # ...user triggers some action...
63
+ config.somevalue = "xyz"
64
+
65
+ # ...days later on a subsquent browser session...
66
+ puts config.somevalue # > "xyz" not "abc" - Yay!
67
+
68
+ For more examples, look at the `config_spec.rb` and `storage_spec.rb` files in the `spec` folder.
69
+
70
+ ## Contributing
71
+
72
+ 1. Fork it ( http://github.com/jaredcwhite/opal-shimmer/fork )
73
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
74
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
75
+ 4. Push to the branch (`git push origin my-new-feature`)
76
+ 5. Create new Pull Request
77
+
78
+ ## Testing
79
+
80
+ Simply run `rackup` at your command line when you're in the project folder. It will load a webserver at port 9292. Then just go to your browser and access `http://localhost:9292`. You should get the full rspec suite runner output. (And hopefully, everything's green!)
81
+
82
+ _If you have trouble using Safari, try using Chrome instead. I'm not sure why this is sometimes an issue..._
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+
4
+ run Opal::Server.new { |s|
5
+ s.main = 'opal/rspec/sprockets_runner'
6
+ s.append_path 'spec'
7
+ s.debug = false
8
+ }
@@ -0,0 +1 @@
1
+ require 'opal/shimmer'
@@ -0,0 +1,5 @@
1
+ require 'opal'
2
+ require 'opal/shimmer/version'
3
+
4
+ # Just register our opal code path with opal build tools
5
+ Opal.append_path File.expand_path('../../../opal', __FILE__)
@@ -0,0 +1,5 @@
1
+ module Opal
2
+ module Shimmer
3
+ VERSION = "0.1.1"
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'opal/shimmer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "opal-shimmer"
8
+ spec.version = Opal::Shimmer::VERSION
9
+ spec.authors = ["Jared White"]
10
+ spec.email = ["jared@ealchemylabs.com"]
11
+ spec.description = %q{An application state and configuration management library built with Opal}
12
+ spec.summary = spec.description
13
+ spec.homepage = "https://github.com/jaredcwhite/opal-shimmer"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'opal', '~> 0.7.0.beta1'
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency 'opal-rspec', '~> 0.4.0.beta2'
25
+ end
@@ -0,0 +1,4 @@
1
+ require 'set'
2
+ require 'json'
3
+ require 'shimmer/storage'
4
+ require 'shimmer/config'
@@ -0,0 +1,127 @@
1
+ module Shimmer
2
+
3
+ class Config
4
+ DEFAULT_CONFIG_PATH = "config"
5
+
6
+ def initialize(parent_key=nil, parent_level=nil)
7
+ @parent_key = parent_key
8
+ @parent_level = parent_level
9
+ @store = {}
10
+ @persisted_storage = Shimmer::Storage.new(self)
11
+ @in_persisting_block = false
12
+ end
13
+
14
+ def parent_level
15
+ @parent_level
16
+ end
17
+ def parent_key
18
+ @parent_key || self.class::DEFAULT_CONFIG_PATH
19
+ end
20
+
21
+ def method_missing(input_method_name, *args, &block)
22
+ method_name = input_method_name.to_s
23
+
24
+ if method_name[-1] == "="
25
+ save_key = method_name[0..-2]
26
+ if @in_persisting_block
27
+ unless @persisted_storage.should_include?(save_key)
28
+ @persisted_storage.should_include(save_key)
29
+ end
30
+ unless @persisted_storage.include?(save_key)
31
+ @persisted_storage.save_value(save_key, args[0])
32
+ end
33
+ elsif !@in_persisting_block and @persisted_storage.should_include?(save_key)
34
+ @store[save_key] = args[0]
35
+ @persisted_storage.save_value(save_key, args[0])
36
+ else
37
+ @store[save_key] = args[0]
38
+ end
39
+ else
40
+ if include?(method_name)
41
+ yield @store[method_name] if block
42
+ @store[method_name]
43
+ elsif @persisted_storage.should_include?(method_name)
44
+ @store[method_name] = @persisted_storage.load_value(method_name)
45
+ yield @store[method_name] if block
46
+ @store[method_name]
47
+ else
48
+ new_config = self.class.new(method_name, self)
49
+ yield new_config if block
50
+ @store[method_name] = new_config
51
+ end
52
+ end
53
+ end
54
+
55
+ def persist(*keys)
56
+ keys = [keys] unless keys.is_a?(Array)
57
+ keys.each do |key|
58
+ @persisted_storage.should_include(key)
59
+ end
60
+ end
61
+
62
+ def persist_defaults(&block)
63
+ @in_persisting_block = true
64
+ yield self
65
+ @in_persisting_block = false
66
+ end
67
+
68
+ def generate_key_path
69
+ if @parent_level
70
+ path_segments = [@parent_key]
71
+ reached_top = false
72
+ current_level = @parent_level
73
+
74
+ until reached_top
75
+ if current_level and current_level.parent_key
76
+ path_segments << current_level.parent_key
77
+ current_level = current_level.parent_level
78
+ else
79
+ reached_top = true
80
+ end
81
+ end
82
+
83
+ path_segments.reverse.join(".")
84
+ elsif @parent_key
85
+ @parent_key
86
+ else
87
+ self.class::DEFAULT_CONFIG_PATH
88
+ end
89
+ end
90
+
91
+ def include?(key)
92
+ @store.include?(key)
93
+ end
94
+
95
+ def delete(key)
96
+ if @persisted_storage.should_include?(key)
97
+ @persisted_storage.delete_value(key)
98
+ end
99
+ @store.delete(key)
100
+ end
101
+
102
+ def nil?
103
+ @store.length == 0
104
+ end
105
+
106
+ def to_s
107
+ if @store.length == 0
108
+ ""
109
+ else
110
+ @store.inspect
111
+ end
112
+ end
113
+
114
+ def to_i
115
+ 0
116
+ end
117
+
118
+ def to_bool
119
+ false
120
+ end
121
+
122
+ def to_h
123
+ @store
124
+ end
125
+ end
126
+
127
+ end
@@ -0,0 +1,38 @@
1
+ module Shimmer
2
+ class Storage
3
+ def initialize(config_object)
4
+ @config_object = config_object
5
+ @storage_path = config_object.generate_key_path
6
+ @include_keys = Set.new
7
+ end
8
+
9
+ def load_value(key)
10
+ json_value = `window.localStorage[#{@storage_path + '.' + key}]`
11
+ if `json_value != null`
12
+ JSON.parse(json_value)
13
+ else
14
+ nil
15
+ end
16
+ end
17
+
18
+ def save_value(key, value)
19
+ `window.localStorage[#{@storage_path + '.' + key}] = #{JSON.dump(value)}`
20
+ end
21
+
22
+ def should_include?(key)
23
+ @include_keys.include?(key)
24
+ end
25
+ def should_include(key)
26
+ @include_keys << key
27
+ end
28
+
29
+ def include?(key)
30
+ `window.localStorage[#{@storage_path + '.' + key}] != null`
31
+ end
32
+
33
+ def delete_value(key)
34
+ @include_keys.delete(key)
35
+ `window.localStorage.removeItem(#{@storage_path + '.' + key})`
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Shimmer::Config" do
4
+ let(:config) { config = Shimmer::Config.new }
5
+
6
+ it "can set a single value" do
7
+ config.somevalue = "Wow"
8
+
9
+ expect(config.somevalue).to eq("Wow")
10
+ end
11
+
12
+ it "can set a namespaced valued" do
13
+ config.namespace.coolvalue = "Way awesome!"
14
+
15
+ expect(config.namespace.coolvalue).to eq("Way awesome!")
16
+ end
17
+
18
+ it "can check nil when something doesn't exist" do
19
+ expect(config.foo.nil?).to eq(true)
20
+ end
21
+
22
+ it "can call to_s on a blank value to get a blank string" do
23
+ expect(config.nothing.elsewill.matter.to_s).to eq("")
24
+ end
25
+
26
+ it "can call to_i on a blank value to get 0" do
27
+ expect(config.supah.cool.to_i).to eq(0)
28
+ end
29
+
30
+ it "can call to_bool on a blank value to get false" do
31
+ expect(config.golden.gate.to_bool).to eq(false)
32
+ end
33
+
34
+ it "can get a string printout of options" do
35
+ config.namespace.firstvalue = "abc"
36
+ config.namespace.secondvalue = 123
37
+
38
+ expect(config.namespace.to_s).to eq("{\"firstvalue\"=>\"abc\", \"secondvalue\"=>123}")
39
+ end
40
+
41
+ it "can get an options hash" do
42
+ config.namespace.firstvalue = "abc"
43
+ config.namespace.secondvalue = 123
44
+
45
+ expect(config.namespace.to_h).to be_a(Hash)
46
+ end
47
+
48
+ it "can set a previous value to nil" do
49
+ config.avalue = [0,5,10]
50
+ config.avalue = nil
51
+
52
+ expect(config.avalue.nil?).to eq(true)
53
+ end
54
+
55
+ it "can check for existance of a value" do
56
+ expect(config.include?(:avalue)).to eq(false)
57
+ config.avalue = [0,5,10]
58
+ expect(config.include?(:avalue)).to eq(true)
59
+ expect(config.some.nested.include?(:avalue)).to eq(false)
60
+ config.some.nested.avalue = {:foo => "bar"}
61
+ expect(config.some.nested.include?(:avalue)).to eq(true)
62
+ expect(config.some.include?(:nested)).to eq(true)
63
+ expect(config.some.include?(:bested)).to eq(false)
64
+ end
65
+
66
+ it "supports a block / tap style setting" do
67
+ config.really.deep.namespace do |c|
68
+ c.value1 = 1
69
+ c.value2 = 2
70
+ end
71
+ expect(config.really.deep.namespace.value2).to eq(2)
72
+ end
73
+ end
@@ -0,0 +1 @@
1
+ require 'shimmer'
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Shimmer::Storage" do
4
+ let(:config) { config = Shimmer::Config.new }
5
+
6
+ it "generates correct paths" do
7
+ config.somevalue = "Wow"
8
+ expect(config.generate_key_path).to eq("config")
9
+
10
+ config.several.levels.deep.lurks = "a monster!"
11
+ expect(config.several.levels.deep.generate_key_path).to eq("config.several.levels.deep")
12
+
13
+ config2 = Shimmer::Config.new(:config2)
14
+ config2.properly.namespaces.itself = "which is cool"
15
+ expect(config2.properly.namespaces.generate_key_path).to eq("config2.properly.namespaces")
16
+ end
17
+
18
+ it "persists a value" do
19
+ config.persist(:cease_and_persist)
20
+ config.cease_and_persist = "abc123"
21
+
22
+ config2 = Shimmer::Config.new
23
+ config2.persist(:cease_and_persist)
24
+ expect(config2.cease_and_persist).to eq("abc123")
25
+ end
26
+
27
+ it "works with complex values" do
28
+ config.persist(:somebool, :somearray, :somehash)
29
+
30
+ config.somebool = true
31
+ config.somearray = [3, 9, "a", false]
32
+ config.somehash = {foo: "bar", baz: [3, 9]}
33
+
34
+ config2 = Shimmer::Config.new
35
+ config2.persist(:somebool, :somearray, :somehash)
36
+
37
+ expect(config2.somebool).to eq(true)
38
+ expect(config2.somearray).to eq([3, 9, "a", false])
39
+ expect(config2.somehash).to eq({foo: "bar", baz: [3, 9]})
40
+ end
41
+
42
+ it "works with namespaces" do
43
+ config.namespaced.persist(:avalue)
44
+ config.namespaced do |spaced|
45
+ spaced.avalue = "Groovy!"
46
+ end
47
+
48
+ config2 = Shimmer::Config.new
49
+ config2.namespaced.persist(:avalue)
50
+ expect(config2.namespaced.avalue).to eq("Groovy!")
51
+ end
52
+
53
+ it "allows for default values" do
54
+ # we have to make sure localStorage is nulled out here, otherwise
55
+ # the test will fail after the first time it's run :)
56
+ `window.localStorage.removeItem('config.somevalue')`
57
+ `window.localStorage.removeItem('config.othervalue')`
58
+
59
+ config.persist_defaults do |c|
60
+ c.somevalue = "abc"
61
+ c.othervalue = 123
62
+ end
63
+
64
+ expect(config.somevalue).to eq("abc")
65
+
66
+ config.somevalue = "xyz"
67
+ expect(config.somevalue).to eq("xyz")
68
+
69
+ config2 = Shimmer::Config.new
70
+ config2.persist_defaults do |c|
71
+ c.somevalue = "abc"
72
+ c.othervalue = 123
73
+ end
74
+
75
+ expect(config2.somevalue).to eq("xyz")
76
+ expect(config2.othervalue).to eq(123)
77
+ end
78
+
79
+ it "can delete a value" do
80
+ # we have to make sure localStorage is nulled out here, otherwise
81
+ # the test will fail after the first time it's run :)
82
+ `window.localStorage.removeItem('config.somevalue')`
83
+ `window.localStorage.removeItem('config.othervalue')`
84
+
85
+ config.persist_defaults do |c|
86
+ c.somevalue = "abc"
87
+ c.othervalue = 123
88
+ end
89
+
90
+ expect(config.somevalue).to eq("abc")
91
+
92
+ config.somevalue = "xyz"
93
+ expect(config.somevalue).to eq("xyz")
94
+
95
+ config.delete(:somevalue)
96
+
97
+ config2 = Shimmer::Config.new
98
+ config2.persist_defaults do |c|
99
+ c.somevalue = "abc"
100
+ c.othervalue = 123
101
+ end
102
+
103
+ expect(config2.somevalue).to eq("abc")
104
+ expect(config2.othervalue).to eq(123)
105
+ end
106
+
107
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opal-shimmer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Jared White
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: opal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.0.beta1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.0.beta1
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: opal-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.4.0.beta2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.4.0.beta2
69
+ description: An application state and configuration management library built with
70
+ Opal
71
+ email:
72
+ - jared@ealchemylabs.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".ruby-version"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - config.ru
84
+ - lib/opal-shimmer.rb
85
+ - lib/opal/shimmer.rb
86
+ - lib/opal/shimmer/version.rb
87
+ - opal-shimmer.gemspec
88
+ - opal/shimmer.rb
89
+ - opal/shimmer/config.rb
90
+ - opal/shimmer/storage.rb
91
+ - spec/config_spec.rb
92
+ - spec/spec_helper.rb
93
+ - spec/storage_spec.rb
94
+ homepage: https://github.com/jaredcwhite/opal-shimmer
95
+ licenses:
96
+ - MIT
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.2.2
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: An application state and configuration management library built with Opal
118
+ test_files:
119
+ - spec/config_spec.rb
120
+ - spec/spec_helper.rb
121
+ - spec/storage_spec.rb