bound 0.0.5 → 0.0.6

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: 19c4132942443826a69acf31323e7aa1383e4901
4
- data.tar.gz: a227951c47f6e073371f6134f16a193e7f349d49
3
+ metadata.gz: 407f1b12ba2b429451193286bed998eb48a47fcb
4
+ data.tar.gz: b97c11dcaa8c42fe8eda4291d9653a3722a14ceb
5
5
  SHA512:
6
- metadata.gz: 0d06853ef334dcb348d5765d7eb9b47695fd78cfa30a010e3baa5ba311ad61f7b4f6f7a488a4fcdb8b7c68241470bb0203c4ae71185efad1fffbbf19261ca580
7
- data.tar.gz: 2a3cabfd7c91b7c127406afe68ba7205421d6e41c6ae8c79bb4af6f65fef651a4386075010cf0011e9bb419160b845bd614c870db3196f65ff448b64b3c57941
6
+ metadata.gz: 93d70c496b9f16d3380620e56b48e7de691069cbd1d29c156184470b25db29dc096477cab62ed576c413c9a1874add6dcd8298a1bef8a153e7383696ebf60ca1
7
+ data.tar.gz: ffe2af419bf9692707cca7ef4442103dbc42666fa989a24bc02e6accc031cba31a20ade6027af97cc40be28b59e0bcb9f3f3a9c7cf7a7b7d459274ed7b66d6ed
@@ -15,13 +15,14 @@ class Bound
15
15
 
16
16
  class BoundClass
17
17
  class << self
18
- attr_accessor :attributes, :optionals
18
+ attr_accessor :attributes, :optionals, :nested
19
19
 
20
20
  def set_attributes(*attributes)
21
21
  self.attributes = attributes
22
22
  attr_accessor *attributes
23
23
 
24
- self.optionals = []
24
+ self.optionals = []
25
+ self.nested = []
25
26
  end
26
27
 
27
28
  def optional(*optionals)
@@ -31,6 +32,24 @@ class Bound
31
32
  self
32
33
  end
33
34
 
35
+ def nested(nested_attributes)
36
+ attributes = nested_attributes.keys
37
+ self.nested = attributes
38
+ self.attributes += attributes
39
+ attr_reader *attributes
40
+
41
+ attributes.each do |attribute|
42
+ define_method :"#{attribute}=" do |initial_values|
43
+ nested_target = nested_attributes[attribute]
44
+ value = extract_values_for_nested_attribute(nested_target, initial_values)
45
+
46
+ instance_variable_set :"@#{attribute}", value
47
+ end
48
+ end
49
+
50
+ self
51
+ end
52
+
34
53
  alias :build :new
35
54
  end
36
55
 
@@ -57,6 +76,22 @@ class Bound
57
76
 
58
77
  private
59
78
 
79
+ def build_nested_value(bound_class, init)
80
+ bound_class.new(init)
81
+ end
82
+
83
+ def extract_values_for_nested_attribute(nested_target, initial_values)
84
+ if nested_target.kind_of? Array
85
+ raise ArgumentError.new("Expected #{initial_values.inspect} to be an array") unless initial_values.kind_of? Array
86
+
87
+ initial_values.map do |initial_value|
88
+ build_nested_value(nested_target.first, initial_value)
89
+ end
90
+ else
91
+ build_nested_value(nested_target, initial_values)
92
+ end
93
+ end
94
+
60
95
  def validate!
61
96
  self.class.attributes.each do |attribute|
62
97
  raise ArgumentError.new("Missing attribute: #{attribute}") unless @hash.key?(attribute)
@@ -1,3 +1,3 @@
1
1
  class Bound
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -113,4 +113,57 @@ describe Bound do
113
113
  UserWithoutAttributes.build
114
114
  end
115
115
  end
116
+
117
+ describe 'nested attribute' do
118
+ Company = Bound.new(:name).nested(:address => Bound.new(:street))
119
+ EmployedUser = Bound.new(:uid).nested(:company => Company)
120
+ let(:hash) { {:uid => '1', :company => {:name => 'featurepoly', :address => {:street => 'Germany'}}} }
121
+
122
+ it 'works with nested attributes' do
123
+ [hash, object].each do |subject|
124
+ user = EmployedUser.build(subject)
125
+
126
+ assert_equal hash[:uid], user.uid
127
+ assert_equal hash[:company][:name], user.company.name
128
+ assert_equal hash[:company][:address][:street], user.company.address.street
129
+ end
130
+ end
131
+ end
132
+
133
+ describe 'array of nested attribute' do
134
+ Post = Bound.new(:title)
135
+ BloggingUser = Bound.new(:name).nested(:posts => [Post])
136
+ let(:hash) do
137
+ {
138
+ :name => 'Steve',
139
+ :posts => [
140
+ {:title => 'It is christmas'},
141
+ {:title => 'NOT'}
142
+ ]
143
+ }
144
+ end
145
+
146
+ it 'works with array of nested attributes' do
147
+ [hash, object].each do |subject|
148
+ user = BloggingUser.build(subject)
149
+
150
+ assert_equal hash[:name], user.name
151
+ assert_equal hash[:posts][0][:title], user.posts[0].title
152
+ assert_equal hash[:posts][1][:title], user.posts[1].title
153
+ end
154
+ end
155
+
156
+ it 'fails if posts is no array' do
157
+ hash[:posts] = {:title => 'broken'}
158
+
159
+ [hash, object].each do |subject|
160
+ exception = assert_raises ArgumentError do
161
+ BloggingUser.build(subject)
162
+ end
163
+
164
+ assert_match(/array/i, exception.message)
165
+ end
166
+
167
+ end
168
+ end
116
169
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ # Test support object
4
+ describe HashObject do
5
+
6
+ subject { HashObject.new(hash) }
7
+ let(:hash) do
8
+ {
9
+ :name => 'Steve',
10
+ :address => {:street => 'Mainstreet'},
11
+ :posts => [
12
+ {:title => 'It is christmas'},
13
+ {:title => 'NOT'}
14
+ ]
15
+ }
16
+ end
17
+
18
+ it 'maps an intergalactic hash' do
19
+ assert_equal hash[:name], subject.name
20
+ assert_equal hash[:address][:street], subject.address.street
21
+ assert_equal hash[:posts].size, subject.posts.size
22
+ assert_equal hash[:posts][0][:title], subject.posts[0].title
23
+ assert_equal hash[:posts][1][:title], subject.posts[1].title
24
+ end
25
+ end
@@ -19,7 +19,19 @@ class HashObject
19
19
  if attributes.empty?
20
20
  Class.new
21
21
  else
22
- Struct.new(*attributes).new(*values)
22
+ mapped_values = values.map { |v| map_value(v) }
23
+ Struct.new(*attributes).new(*mapped_values)
24
+ end
25
+ end
26
+
27
+ def self.map_value(value)
28
+ case value
29
+ when Hash
30
+ HashObject.new(value)
31
+ when Array
32
+ value.map { |v| map_value(v) }
33
+ else
34
+ value
23
35
  end
24
36
  end
25
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bound
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakob Holderbaum
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-21 00:00:00.000000000 Z
12
+ date: 2013-09-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -70,6 +70,7 @@ files:
70
70
  - lib/bound.rb
71
71
  - lib/bound/version.rb
72
72
  - spec/bound_spec.rb
73
+ - spec/hash_object_spec.rb
73
74
  - spec/spec_helper.rb
74
75
  homepage: ''
75
76
  licenses:
@@ -97,4 +98,5 @@ specification_version: 4
97
98
  summary: Implements a nice helper for fast boundary definitions
98
99
  test_files:
99
100
  - spec/bound_spec.rb
101
+ - spec/hash_object_spec.rb
100
102
  - spec/spec_helper.rb