dish 0.0.2 → 0.0.3

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: 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