dish 0.0.2 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b80bdc6eac863a3ca01536cb0af8034ebfdab5a3
4
- data.tar.gz: 993e1729fc762ebbdd7857e1c17f162a3c48d476
3
+ metadata.gz: f491f4e6dd55335d75c28db8a8cbfc68f5ef445e
4
+ data.tar.gz: 56472250206b5de7862205d6074fcb3233cb1bc8
5
5
  SHA512:
6
- metadata.gz: 7b219fc03d52b0dbdf9610d583cd2e76af17665fefec414dadade3bbf9c8379ef070923d0b4715903e09834bb3538196c2e97156eec41028a53b505b40ac8b86
7
- data.tar.gz: 7fc189d6b1fee5c77d6ea06a8afeb40f5009be2797fe35a885acf71cd6c6a994170b0a131163cd694e77e47609b1b9b4490460392f900f320a2e09e054c8bbf7
6
+ metadata.gz: c652e54b74c3d55db537774ccace1a900fc89a74bfb88f3d12d88474e8226167da3c1cd840823813e5de60c11146f46811ccacea444d0554b7048b041fb247a1
7
+ data.tar.gz: fcc7e13e2b51c93012f6b0058a0f1dfd81c0f52cece0e6a7686b994b3295aac6f442d045fc06eca52bb7efbaadac1390f3f1f9d2cfc52f641691916041530316
@@ -0,0 +1,6 @@
1
+ # Changelog
2
+
3
+ ## 0.0.3
4
+
5
+ * Adds coercion. See the readme for details.
6
+ * Adds an `as_hash` method for accessing the original source hash.
data/README.md CHANGED
@@ -41,7 +41,7 @@ And you're good to go.
41
41
 
42
42
  Note: If you're using Dish with the BubbleWrap JSON module, please see below.
43
43
 
44
- # Example
44
+ ## Example
45
45
 
46
46
  hash = {
47
47
  title: "My Title",
@@ -61,6 +61,58 @@ Note: If you're using Dish with the BubbleWrap JSON module, please see below.
61
61
  book.other # => nil
62
62
  book.other? # => false
63
63
 
64
+ ## Coercion
65
+
66
+ Values can automatically be coerced, for example into a custom `Dish` object or a `Time`, for example if you have an `updated_at` in the source.
67
+
68
+ ```ruby
69
+ class Author < Dish::Plate; end
70
+
71
+ class Product < Dish::Plate
72
+ coerce :updated_at, -> (value) { Time.parse(value) }
73
+ coerce :authors, Author
74
+ end
75
+
76
+ source_products = [
77
+ {
78
+ title: "Test Product",
79
+ updated_at: "2013-01-28 13:23:11",
80
+ authors: [
81
+ { id: 1, name: "First Author" },
82
+ { id: 2, name: "Second Author" }
83
+ ]
84
+ },
85
+ {
86
+ title: "Second Product",
87
+ updated_at: "2012-07-11 19:54:07",
88
+ authors: [
89
+ { id: 1, name: "Third Author" },
90
+ { id: 2, name: "Fourth Author" }
91
+ ]
92
+ }
93
+ ]
94
+
95
+ products = Dish(source_products, Product)
96
+ products.first.updated_at # => instance of Time (2013-01-28 13:23:11)
97
+ products.first.authors.first # => instance of Author
98
+
99
+ # If you required "dish/ext", you can also:
100
+ products = source_products.to_dish(Product)
101
+
102
+ # The above example uses an array. You can do the same directly on a hash:
103
+ hash = { title: "My Product", updated_at: "2014-01-15 09:12:45" }
104
+ product = Dish(hash, Product) # => instance of Product
105
+ product = hash.to_dish(Product) # => instance of Product when using "dish/ext"
106
+ ```
107
+
108
+ This is inspired by [Hashie](https://github.com/intridea/hashie)'s coercion methods.
109
+
110
+ Have fun!
111
+
112
+ ## Accessing the original hash
113
+
114
+ You can use the `as_hash` method for accessing the original hash.
115
+
64
116
  ## Notes
65
117
 
66
118
  ### Using with the BubbleWrap JSON module
@@ -1,5 +1,5 @@
1
1
  class Array
2
- def to_dish
3
- Dish(self)
2
+ def to_dish(klass = Dish::Plate)
3
+ Dish(self, klass)
4
4
  end
5
5
  end
@@ -1,5 +1,5 @@
1
1
  class Hash
2
- def to_dish
3
- Dish(self)
2
+ def to_dish(klass = Dish::Plate)
3
+ Dish(self, klass)
4
4
  end
5
5
  end
@@ -1,7 +1,7 @@
1
- def Dish(hash_or_array)
1
+ def Dish(hash_or_array, klass = Dish::Plate)
2
2
  case hash_or_array
3
- when Hash then Dish::Plate.new(hash_or_array)
4
- when Array then hash_or_array.map { |v| Dish(v) }
3
+ when Hash then klass.new(hash_or_array)
4
+ when Array then hash_or_array.map { |v| Dish(v, klass) }
5
5
  else hash_or_array
6
6
  end
7
7
  end
@@ -1,43 +1,61 @@
1
1
  module Dish
2
2
  class Plate
3
+ class << self
4
+ def coercions
5
+ @coercions ||= Hash.new(Plate)
6
+ end
7
+
8
+ def coerce(key, klass_or_proc)
9
+ coercions[key.to_s] = klass_or_proc
10
+ end
11
+ end
12
+
3
13
  def initialize(hash)
4
- @dish_original_hash = Hash[hash.map { |k, v| [k.to_s, v] }]
14
+ @_original_hash = Hash[hash.map { |k, v| [k.to_s, v] }]
5
15
  end
6
16
 
7
17
  def method_missing(method, *args, &block)
8
18
  method = method.to_s
9
19
  if method.end_with?("?")
10
20
  key = method[0..-2]
11
- dish_check_for_presence(key)
21
+ _check_for_presence(key)
12
22
  else
13
- dish_get_value(method)
23
+ _get_value(method)
14
24
  end
15
25
  end
16
26
 
27
+ def as_hash
28
+ @_original_hash
29
+ end
30
+
17
31
  private
18
32
 
19
- attr_reader :dish_original_hash
33
+ attr_reader :_original_hash
20
34
 
21
- def dish_get_value(key)
22
- value = dish_original_hash[key]
23
- dish_convert_value(value)
35
+ def _get_value(key)
36
+ value = _original_hash[key]
37
+ _convert_value(value, self.class.coercions[key])
24
38
  end
25
39
 
26
- def dish_check_for_presence(key)
27
- !!dish_get_value(key)
40
+ def _check_for_presence(key)
41
+ !!_get_value(key)
28
42
  end
29
43
 
30
- def dish_convert_value(value)
44
+ def _convert_value(value, coercion)
31
45
  case value
32
- when Hash then self.class.new(value)
33
- when Array then value.map { |v| dish_convert_value(v) }
34
- else value
35
- end
36
- end
37
-
38
- def dish_metaclass
39
- class << self
40
- self
46
+ when Array then value.map { |v| _convert_value(v, coercion) }
47
+ when Hash
48
+ if coercion.is_a?(Proc)
49
+ coercion.call(value)
50
+ else
51
+ coercion.new(value)
52
+ end
53
+ else
54
+ if coercion.is_a?(Proc)
55
+ coercion.call(value)
56
+ else
57
+ value
58
+ end
41
59
  end
42
60
  end
43
61
  end
@@ -1,3 +1,3 @@
1
1
  module Dish
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,63 @@
1
+ require "test_helper"
2
+
3
+ class DishTest < Test::Unit::TestCase
4
+ def test_coercion
5
+ product = Dish(api_response.first, Product)
6
+
7
+ assert_equal Time.new(2013, 1, 28, 13, 23, 11), product.updated_at
8
+ assert product.authors.all? { |a| a.is_a? Author }
9
+ assert_equal ["First Author", "Second Author"], product.authors.map(&:name)
10
+ end
11
+
12
+ def test_hash_helper_coercion
13
+ product = api_response.first.to_dish(Product)
14
+
15
+ assert_equal Time.new(2013, 1, 28, 13, 23, 11), product.updated_at
16
+ assert product.authors.all? { |a| a.is_a? Author }
17
+ assert_equal ["First Author", "Second Author"], product.authors.map(&:name)
18
+ end
19
+
20
+ def test_array_coercion
21
+ products = Dish(api_response, Product)
22
+
23
+ assert products.all? { |p| p.is_a?(Product) }
24
+ assert products.map(&:authors).flatten.all? { |a| a.is_a?(Author) }
25
+ end
26
+
27
+ def test_array_helper_coercion
28
+ products = api_response.to_dish(Product)
29
+
30
+ assert products.all? { |p| p.is_a?(Product) }
31
+ assert products.map(&:authors).flatten.all? { |a| a.is_a?(Author) }
32
+ end
33
+
34
+ private
35
+
36
+ class Author < Dish::Plate; end
37
+
38
+ class Product < Dish::Plate
39
+ coerce :updated_at, -> (value) { Time.parse(value) }
40
+ coerce :authors, Author
41
+ end
42
+
43
+ def api_response
44
+ [
45
+ {
46
+ title: "Test Product",
47
+ updated_at: "2013-01-28 13:23:11",
48
+ authors: [
49
+ { id: 1, name: "First Author" },
50
+ { id: 2, name: "Second Author" }
51
+ ]
52
+ },
53
+ {
54
+ title: "Second Product",
55
+ updated_at: "2012-07-11 19:54:07",
56
+ authors: [
57
+ { id: 1, name: "Third Author" },
58
+ { id: 2, name: "Fourth Author" }
59
+ ]
60
+ }
61
+ ]
62
+ end
63
+ end
@@ -67,6 +67,22 @@ class DishTest < Test::Unit::TestCase
67
67
  assert_nil Dish(nil)
68
68
  end
69
69
 
70
+ def test_as_hash
71
+ hash = {
72
+ "a" => "a",
73
+ "b" => "b",
74
+ "c" => {
75
+ "1" => 1,
76
+ "2" => 2
77
+ }
78
+ }
79
+ dish = Dish(hash)
80
+ c_hash = dish.c.as_hash
81
+ assert_equal "Hash", dish.c.as_hash.class.to_s
82
+ assert_equal hash["c"]["1"], c_hash["1"]
83
+ assert_equal hash["c"]["2"], c_hash["2"]
84
+ end
85
+
70
86
  def test_hash_ext
71
87
  hash = { a: 1, b: 2 }
72
88
  dish = hash.to_dish
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.2
4
+ version: 0.0.3
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-01-13 00:00:00.000000000 Z
11
+ date: 2014-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -48,6 +48,7 @@ extra_rdoc_files: []
48
48
  files:
49
49
  - ".gitignore"
50
50
  - ".travis.yml"
51
+ - CHANGELOG.md
51
52
  - Gemfile
52
53
  - LICENSE.txt
53
54
  - README.md
@@ -61,6 +62,7 @@ files:
61
62
  - lib/dish/motion.rb
62
63
  - lib/dish/plate.rb
63
64
  - lib/dish/version.rb
65
+ - test/coercion_test.rb
64
66
  - test/dish_test.rb
65
67
  - test/test_helper.rb
66
68
  homepage: https://github.com/lassebunk/dish
@@ -88,5 +90,6 @@ signing_key:
88
90
  specification_version: 4
89
91
  summary: Super simple conversion of hashes to plain Ruby objects
90
92
  test_files:
93
+ - test/coercion_test.rb
91
94
  - test/dish_test.rb
92
95
  - test/test_helper.rb