arendelle 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0fb231fcd2a2f086f85f741c07876da50d59e87
4
- data.tar.gz: beabf2e1a62170c754cb5b719c153a76e1e8f26c
3
+ metadata.gz: b8c4731aa741a8c2c04710d88dd8c765def58bc0
4
+ data.tar.gz: 450779ee96a563356f0157d997c76965dd2b76ca
5
5
  SHA512:
6
- metadata.gz: b943a00e6d4dce73cb276cfa9600c7b55bbb5194d0b96a3c0ca713c187936baeae19f36fd1ac9972d6f2c6b64ed19ac453530f88503d54570a644d5dc4f3a9f7
7
- data.tar.gz: 84819e6c0d2c6f3bb4243f52c1f0db12cc6cc2f576c296f057c91801ea8749071ae94ddfb6d2710a348c93a1a5bf91aaf4c66665e11d84093fd7e3fc403cfd22
6
+ metadata.gz: 2316e611e4cd8a45930b5071a608e154570aeb7bf31bc6516c4c2ddd13815389cc6a5052729b961f4259ea63f1754d5899942cd97b8bbf9ab239e59058c6ce1a
7
+ data.tar.gz: 7f61c21e719c80d55398c5c76622d6fee69355ffaec1383b277de9daba175846a70139e653d3d41784440fe9a6d5974916cbb57b948b47424f427831927fead6
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ## [0.1.1] - 2017-03-20
2
+
3
+ Added support for handling JSON keys that start with integers. Previously this was attempting to use an invalid instance variable ("@1234"). New behavior prepends instance variables and method access calls with an underscore: `obj._1234` or `obj.instance_variable_get("_@1234")`.
4
+
5
+ ## [0.1.0] - 2017-03-06
6
+
7
+ Initial version released.
data/README.md CHANGED
@@ -1,10 +1,20 @@
1
1
  # Arendelle
2
2
 
3
- Arendelle is a small gem with a distantly semantic name, used for initializing mostly frozen objects. If you've got kids, you probably already understand.
3
+ Arendelle is a small gem with a distantly semantic name, used for initializing mostly frozen objects. If you've got kids, you probably already understand the name.
4
4
 
5
5
  ## Why?
6
6
 
7
- We primarily use Arendelle in our innternal projects combined with JSON.parse and the `object_class` setting, to initialize (mostly) frozen objects. This helps prevent accidentally mutating the state of a parsed JSON file or configuration class, while providing a javascript object-like interface for accessing deeply nested settings. See usage for more details.
7
+ There are a ton of great Struct-like libraries that focus on immutable values. Some (`ure`, for example) focus on performance and offer a similar interface to Struct for declaring dynamic classes. Others give you the full kitchen sink - featuring any type of object you need, with immutability built in.
8
+
9
+ Our use case was very simple, and yet we found ourselves repeatedly reaching for the same code snippet across multiple projects. We wanted something that offers a simple interface for initializing objects when using JSON.parse (which relies on `[]=` as a setter) or something we could occasionally use as a simple set-it-and-forget-it type of simple PORO.
10
+
11
+ So we built something lightweight, optimized for our current use case: `JSON.parse(json_string, object_class: Arendelle)`. When combined with JSON.parse it builds a clean javascript-object like interface for accessing deeply nested JSON, and for us, removed any concerns about "extra" things the code was doing.
12
+
13
+ Take a look at the source for yourself: you probably don't need our help to write this gem. The surface area is incredibly small. But given the utility we've found using this lib, we figured it couldn't hurt to put it out there. So, here you go, Internet. Enjoy.
14
+
15
+ **tl;dr**
16
+
17
+ Arendelle helps prevent accidentally mutating the state of a parsed JSON file or configuration class, while providing a javascript object-like interface for accessing deeply nested settings (when used in conjunction with `JSON.parse`). See usage for more details.
8
18
 
9
19
  ## Installation
10
20
 
@@ -24,11 +34,44 @@ Or install it yourself as:
24
34
 
25
35
  ## Usage
26
36
 
37
+ ```ruby
38
+ json = '{"user_settings":{"name":"Rob"}}'
39
+ obj = JSON.parse(json, object_class: Arendelle)
40
+
41
+ obj.user_settings.name
42
+ => "Rob"
43
+
44
+ # Variables are frozen after initialization
45
+ obj.user_settings["name"] = "New Name"
46
+ => FrozenVariableError: "Cannot modify frozen variable"
47
+
48
+ # Values are frozen after being set
49
+ name = obj.user_settings.name
50
+ name << "Test"
51
+ => RuntimeError: "can't modify frozen String"
52
+
53
+ # We call these mostly frozen objects, because they aren't 100% immutable: they can have settings added, but not modified
54
+ newobj = Arendelle.new(key1: "value1")
55
+ newobj.key1
56
+ => "value1"
57
+
58
+ newobj["key2"] = "value2"
59
+ newobj.key2
60
+ => "value2"
61
+
62
+ newobj["key1"] = "value3"
63
+ => FrozenVariableError: "Cannot modify frozen variable"
27
64
  ```
65
+
66
+ ```yaml
28
67
  # api_keys.yml
29
68
  defaults: &defaults
30
69
  cool_service:
31
70
  client_secret: <%= ENV["COOL_SERVICE_CLIENT_SECRET"] || "default_value" %>
71
+ ```
72
+
73
+ ```ruby
74
+ # Snippet from our "real-world" use case. For us, this is a replacement for the SettingsLogic gem.
32
75
 
33
76
  # settings.rb
34
77
  class Settings
@@ -48,7 +91,7 @@ class Settings
48
91
  end
49
92
  ```
50
93
 
51
- ```
94
+ ```ruby
52
95
  Settings.cool_service.client_secret
53
96
  => "default_value" # assuming the ENV var isn't set
54
97
  ```
@@ -59,6 +102,12 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
59
102
 
60
103
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
61
104
 
105
+ ## Wishlist
106
+
107
+ Currently, we're using this in conjunction with JSON.parse. In some situations, this is less than ideal, as we will rely on the recursive behavior of JSON.parse to ensure that each object is initialized appropriately - calling it as `JSON.parse({}.to_hash, object_class: Arendelle)` - which is one step too many.
108
+
109
+ Adding a `.build_from_hash` type of class method which efficiently handles recursively transforming hash isn't something we need often, but would be a nice-to-have.
110
+
62
111
  ## Contributing
63
112
 
64
113
  Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/arendelle. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/lib/arendelle.rb CHANGED
@@ -1,18 +1,24 @@
1
1
  class Arendelle
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
 
4
4
  def initialize(**opts)
5
5
  opts.each { |k, v| self[k] = v }
6
6
  end
7
7
 
8
8
  def []=(key, value)
9
- ivar = "@#{key}"
9
+ ivar = "@_#{key}"
10
10
  raise FrozenVariableError if instance_variable_get(ivar)
11
11
 
12
12
  instance_variable_set(ivar, value.freeze)
13
13
 
14
- define_singleton_method(key) do
15
- instance_variable_get(ivar)
14
+ if key[0] =~ /\d/
15
+ define_singleton_method("_#{key}") do
16
+ instance_variable_get(ivar)
17
+ end
18
+ else
19
+ define_singleton_method(key) do
20
+ instance_variable_get(ivar)
21
+ end
16
22
  end
17
23
  end
18
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arendelle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Cole
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-06 00:00:00.000000000 Z
11
+ date: 2017-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -62,12 +62,12 @@ files:
62
62
  - ".gitignore"
63
63
  - ".rspec"
64
64
  - ".travis.yml"
65
+ - CHANGELOG.md
65
66
  - CODE_OF_CONDUCT.md
66
67
  - Gemfile
67
68
  - LICENSE.txt
68
69
  - README.md
69
70
  - Rakefile
70
- - arendelle.gemspec
71
71
  - bin/console
72
72
  - bin/setup
73
73
  - lib/arendelle.rb
data/arendelle.gemspec DELETED
@@ -1,27 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'arendelle'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "arendelle"
8
- spec.version = Arendelle::VERSION
9
- spec.authors = ["Rob Cole"]
10
- spec.email = ["robcole@useed.org"]
11
-
12
- spec.summary = %q{A simple gem for creating mostly frozen objects.
13
- Useful for configuration-like objects.}
14
- spec.homepage = "https://github.com/useed/arendelle"
15
- spec.license = "MIT"
16
-
17
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
- f.match(%r{^(test|spec|features)/})
19
- end
20
- spec.bindir = "exe"
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
23
-
24
- spec.add_development_dependency "bundler", "~> 1.14"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec", "~> 3.0"
27
- end