dish 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +33 -28
- data/lib/dish/plate.rb +40 -6
- data/lib/dish/version.rb +1 -1
- data/test/coercion_test.rb +17 -0
- data/test/deprecated_test.rb +13 -0
- data/test/dish_test.rb +42 -4
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc7f03afd4235d643f705eb69e4090e957e976a4
|
4
|
+
data.tar.gz: 515e6465bb10f1abf86469cd3fdc0774c659c9b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1a8a91507d2d016656d74065e3fafb57843e8abbab074830384f7443b36dd4400c3f0c52060995006c2d65514731063440e500e574ef0c3393554688f29fed2
|
7
|
+
data.tar.gz: c575c4f366a7d8f7c2f5e19f1659b0189447f66560d3bd2b707c1406c6418d05a12acf93db7fdb5fdcb267be5bfce4a0d2625fadaf9fe8949903aa7711d28ae0
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.0.5
|
4
|
+
|
5
|
+
* Supports setting values via `some_dish_object.key = 'value'`.
|
6
|
+
* Values are now cached after their first conversion. This improves performance when calling the same methods repeatedly.
|
7
|
+
* Available keys are returned by the `methods` method on a Dish object.
|
8
|
+
* `as_hash` is deprecated and renamed to `to_h`.
|
9
|
+
* Supports converting the Dish object to json via `to_json`.
|
10
|
+
* `respond_to?` and `respond_to_missing?` now works correctly.
|
11
|
+
|
12
|
+
## 0.0.4
|
13
|
+
|
14
|
+
* Implements `respond_to_missing?`.
|
15
|
+
|
3
16
|
## 0.0.3
|
4
17
|
|
5
18
|
* Adds coercion. See the readme for details.
|
data/README.md
CHANGED
@@ -40,27 +40,28 @@ Then run:
|
|
40
40
|
|
41
41
|
And you're good to go.
|
42
42
|
|
43
|
-
|
43
|
+
**NOTE:** If you're using Dish with the BubbleWrap JSON module, please see below.
|
44
44
|
|
45
45
|
## Example
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
46
|
+
```ruby
|
47
|
+
hash = {
|
48
|
+
title: "My Title",
|
49
|
+
authors: [
|
50
|
+
{ id: 1, name: "Mike Anderson" },
|
51
|
+
{ id: 2, name: "Well D." }
|
52
|
+
],
|
53
|
+
active: false
|
54
|
+
}
|
55
|
+
|
56
|
+
book = Dish(hash) # or hash.to_dish if you required "dish/ext"
|
57
|
+
book.title # => "My Title"
|
58
|
+
book.authors.length # => 2
|
59
|
+
book.authors[1].name # => "Well D."
|
60
|
+
book.title? # => true
|
61
|
+
book.active? # => false
|
62
|
+
book.other # => nil
|
63
|
+
book.other? # => false
|
64
|
+
```
|
64
65
|
|
65
66
|
## Coercion
|
66
67
|
|
@@ -110,25 +111,29 @@ This is inspired by [Hashie](https://github.com/intridea/hashie)'s coercion meth
|
|
110
111
|
|
111
112
|
Have fun!
|
112
113
|
|
113
|
-
##
|
114
|
+
## Converting back to Ruby/JSON objects
|
115
|
+
|
116
|
+
You can use the `Dish::Plate#to_h` method for accessing the original hash. In addition `Dish::Plate#to_json` can be used for marshaling JSON if you are using RubyMotion (`NSJSONSerialization` is used) or have required [the "json" Ruby stdlib](http://www.ruby-doc.org/stdlib/libdoc/json/rdoc/JSON.html).
|
114
117
|
|
115
|
-
|
118
|
+
**NOTE:** Previously `Dish::Plate#to_h` was called `Dish::Plate#as_hash`. The `Dish::Plate#as_hash` method is now deprecated.
|
116
119
|
|
117
120
|
## Notes
|
118
121
|
|
119
122
|
### Using with the BubbleWrap JSON module
|
120
123
|
|
121
124
|
When you use the [BubbleWrap](https://github.com/rubymotion/BubbleWrap) gem to parse JSON into a hash, you can't use the
|
122
|
-
`to_dish` methods directly because the `BW::JSON` module returns some sort of hash that hasn't got the methods from the real hash. I'm
|
125
|
+
`Hash#to_dish` methods directly because the `BW::JSON` module returns some sort of hash that hasn't got the methods from the real hash. I'm
|
123
126
|
fixing this, but in the meanwhile you can achieve the same result by doing this:
|
124
127
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
+
```ruby
|
129
|
+
BW::HTTP.get("http://path.to/api/books/2") do |response|
|
130
|
+
json = BW::JSON.parse(response.body.to_s)
|
131
|
+
book = Dish(json) # This is the actual conversion
|
128
132
|
|
129
|
-
|
130
|
-
|
131
|
-
|
133
|
+
title_label.text = book.title
|
134
|
+
author_label.text = book.authors.map(&:name).join(", ")
|
135
|
+
end
|
136
|
+
```
|
132
137
|
|
133
138
|
## Contributing
|
134
139
|
|
data/lib/dish/plate.rb
CHANGED
@@ -12,13 +12,16 @@ module Dish
|
|
12
12
|
|
13
13
|
def initialize(hash)
|
14
14
|
@_original_hash = Hash[hash.map { |k, v| [k.to_s, v] }]
|
15
|
+
@_value_cache = {}
|
15
16
|
end
|
16
17
|
|
17
18
|
def method_missing(method, *args, &block)
|
18
19
|
method = method.to_s
|
20
|
+
key = method[0..-2]
|
19
21
|
if method.end_with?("?")
|
20
|
-
key
|
21
|
-
|
22
|
+
!!_get_value(key)
|
23
|
+
elsif method.end_with? '='
|
24
|
+
_set_value(key, args.first)
|
22
25
|
else
|
23
26
|
_get_value(method)
|
24
27
|
end
|
@@ -28,21 +31,52 @@ module Dish
|
|
28
31
|
_check_for_presence(method.to_s) || super
|
29
32
|
end
|
30
33
|
|
31
|
-
def
|
34
|
+
def to_h
|
32
35
|
@_original_hash
|
33
36
|
end
|
34
37
|
|
38
|
+
def as_hash
|
39
|
+
# TODO: Add the version number where this was deprecated?
|
40
|
+
warn 'Dish::Plate#as_hash has been deprecated. Use Dish::Plate#to_h.'
|
41
|
+
to_h
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_json(*args)
|
45
|
+
# If we're using RubyMotion #to_json isn't available like with Ruby's JSON stdlib
|
46
|
+
if defined?(Motion::Project::Config)
|
47
|
+
# From BubbleWrap: https://github.com/rubymotion/BubbleWrap/blob/master/motion/core/json.rb#L30-L32
|
48
|
+
NSJSONSerialization.dataWithJSONObject(to_h, options: 0, error: nil).to_str
|
49
|
+
elsif defined?(JSON)
|
50
|
+
to_h.to_json(*args)
|
51
|
+
else
|
52
|
+
raise "#{self.class}#to_json depends on Hash#to_json. Try again after using `require 'json'`."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def methods(regular = true)
|
57
|
+
valid_keys = to_h.keys.map(&:to_sym)
|
58
|
+
valid_keys + super
|
59
|
+
end
|
60
|
+
|
35
61
|
private
|
36
62
|
|
37
63
|
attr_reader :_original_hash
|
38
64
|
|
39
65
|
def _get_value(key)
|
40
66
|
value = _original_hash[key]
|
41
|
-
_convert_value(value, self.class.coercions[key])
|
67
|
+
@_value_cache[_cache_key(value)] ||= _convert_value(value, self.class.coercions[key])
|
42
68
|
end
|
43
69
|
|
70
|
+
def _cache_key(value)
|
71
|
+
[value.object_id, @_original_hash.hash].join('')
|
72
|
+
end
|
73
|
+
|
74
|
+
def _set_value(key, value)
|
75
|
+
@_original_hash[key] = value
|
76
|
+
end
|
77
|
+
|
44
78
|
def _check_for_presence(key)
|
45
|
-
|
79
|
+
_original_hash.key?(key)
|
46
80
|
end
|
47
81
|
|
48
82
|
def _convert_value(value, coercion)
|
@@ -63,4 +97,4 @@ module Dish
|
|
63
97
|
end
|
64
98
|
end
|
65
99
|
end
|
66
|
-
end
|
100
|
+
end
|
data/lib/dish/version.rb
CHANGED
data/test/coercion_test.rb
CHANGED
@@ -32,6 +32,23 @@ class DishTest < Test::Unit::TestCase
|
|
32
32
|
assert products.map(&:authors).flatten.all? { |a| a.is_a?(Author) }
|
33
33
|
end
|
34
34
|
|
35
|
+
def test_coercion_caching
|
36
|
+
products = api_response.to_dish(Product)
|
37
|
+
|
38
|
+
assert_equal products.first.authors.first.object_id, products.first.authors.first.object_id
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_coercion_cache_busting
|
42
|
+
products = api_response.to_dish(Product)
|
43
|
+
|
44
|
+
author = products.first.authors.first
|
45
|
+
assert_equal author.name, products.first.authors.first.name
|
46
|
+
|
47
|
+
products.first.to_h['authors'].first['name'] = 'Johnny Cache'
|
48
|
+
|
49
|
+
assert_not_equal author.name, products.first.authors.first.name
|
50
|
+
end
|
51
|
+
|
35
52
|
private
|
36
53
|
|
37
54
|
class Author < Dish::Plate; end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class DeprecatedTest < Test::Unit::TestCase
|
4
|
+
def test_deprecated_as_hash
|
5
|
+
p = Dish({ a: 1, b: 2 })
|
6
|
+
|
7
|
+
out, err = capture_io do
|
8
|
+
assert_equal({ "a" => 1, "b" => 2}, p.as_hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
assert_match /Dish::Plate#as_hash has been deprecated\./, err
|
12
|
+
end
|
13
|
+
end
|
data/test/dish_test.rb
CHANGED
@@ -24,7 +24,7 @@ class DishTest < Test::Unit::TestCase
|
|
24
24
|
assert_respond_to book, :authors
|
25
25
|
refute_respond_to book, :doesnotexist
|
26
26
|
assert_nothing_raised do
|
27
|
-
|
27
|
+
book.method(:title)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -73,7 +73,7 @@ class DishTest < Test::Unit::TestCase
|
|
73
73
|
assert_nil Dish(nil)
|
74
74
|
end
|
75
75
|
|
76
|
-
def
|
76
|
+
def test_to_h
|
77
77
|
hash = {
|
78
78
|
"a" => "a",
|
79
79
|
"b" => "b",
|
@@ -83,8 +83,8 @@ class DishTest < Test::Unit::TestCase
|
|
83
83
|
}
|
84
84
|
}
|
85
85
|
dish = Dish(hash)
|
86
|
-
c_hash = dish.c.
|
87
|
-
assert_equal "Hash", dish.c.
|
86
|
+
c_hash = dish.c.to_h
|
87
|
+
assert_equal "Hash", dish.c.to_h.class.to_s
|
88
88
|
assert_equal hash["c"]["1"], c_hash["1"]
|
89
89
|
assert_equal hash["c"]["2"], c_hash["2"]
|
90
90
|
end
|
@@ -107,4 +107,42 @@ class DishTest < Test::Unit::TestCase
|
|
107
107
|
assert_instance_of Dish::Plate, d
|
108
108
|
end
|
109
109
|
end
|
110
|
+
|
111
|
+
def test_respond_to
|
112
|
+
hash = { a: 1, b: true, c: false, d: nil }
|
113
|
+
dish = Dish(hash)
|
114
|
+
|
115
|
+
hash.each do |key, _|
|
116
|
+
assert_respond_to dish, key
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_set_value
|
121
|
+
hash = { a: 1, b: 2, c: false }
|
122
|
+
dish = Dish(hash)
|
123
|
+
|
124
|
+
dish.a = "other value"
|
125
|
+
assert_equal "other value", dish.a
|
126
|
+
|
127
|
+
dish.b = nil
|
128
|
+
assert_equal nil, dish.b
|
129
|
+
assert_equal false, dish.b?
|
130
|
+
|
131
|
+
dish.c = true
|
132
|
+
assert_equal true, dish.c
|
133
|
+
assert_equal true, dish.c?
|
134
|
+
|
135
|
+
dish.d = "new value"
|
136
|
+
assert_equal "new value", dish.d
|
137
|
+
|
138
|
+
assert_equal({ "a" => "other value", "b" => nil, "c" => true, "d" => "new value" },
|
139
|
+
dish.to_h)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_methods
|
143
|
+
hash = { a: 1, b: 2 }
|
144
|
+
dish = Dish(hash)
|
145
|
+
|
146
|
+
assert_equal [:a, :b], dish.methods[0..1]
|
147
|
+
end
|
110
148
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lasse Bunk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- lib/dish/plate.rb
|
64
64
|
- lib/dish/version.rb
|
65
65
|
- test/coercion_test.rb
|
66
|
+
- test/deprecated_test.rb
|
66
67
|
- test/dish_test.rb
|
67
68
|
- test/test_helper.rb
|
68
69
|
homepage: https://github.com/lassebunk/dish
|
@@ -91,5 +92,6 @@ specification_version: 4
|
|
91
92
|
summary: Super simple conversion of hashes to plain Ruby objects
|
92
93
|
test_files:
|
93
94
|
- test/coercion_test.rb
|
95
|
+
- test/deprecated_test.rb
|
94
96
|
- test/dish_test.rb
|
95
97
|
- test/test_helper.rb
|