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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 617dbc0f6b27306fc59b7b9779c60470c050c0da
4
- data.tar.gz: fcd386da110affa4a0e381e7dc7acac6277c76b1
3
+ metadata.gz: cc7f03afd4235d643f705eb69e4090e957e976a4
4
+ data.tar.gz: 515e6465bb10f1abf86469cd3fdc0774c659c9b0
5
5
  SHA512:
6
- metadata.gz: e356555d49c23b40f8c581a5f35dd3270bfab0d169a94cb0ada1a45e7872371b6a7048c5a1d9db8c8d77492bf88f650feddfa25fd5c6ea5df4e9bb2157b2417a
7
- data.tar.gz: 0be9973a4b2a2a6c0cb7863c87ef2ab506b727c45c525a0514173b5f10d51fb02f59741fcac060edcaee3ca97788b8add3b1d3bad4cf2b11f8672a0424c169bb
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
- Note: If you're using Dish with the BubbleWrap JSON module, please see below.
43
+ **NOTE:** If you're using Dish with the BubbleWrap JSON module, please see below.
44
44
 
45
45
  ## Example
46
-
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
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
- ## Accessing the original hash
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
- You can use the `as_hash` method for accessing the original hash.
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
- BW::HTTP.get("http://path.to/api/books/2") do |response|
126
- json = BW::JSON.parse(response.body.to_s)
127
- book = Dish(json) # This is the actual conversion
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
- title_label.text = book.title
130
- author_label.text = book.authors.map(&:name).join(", ")
131
- end
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 = method[0..-2]
21
- _check_for_presence(key)
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 as_hash
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
- !!_get_value(key)
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
@@ -1,3 +1,3 @@
1
1
  module Dish
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -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
- m = book.method(:title)
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 test_as_hash
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.as_hash
87
- assert_equal "Hash", dish.c.as_hash.class.to_s
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
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-09-23 00:00:00.000000000 Z
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