constructable 0.3.4 → 0.4.0
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.
- data/README.markdown +12 -43
- data/VERSION +1 -1
- data/constructable.gemspec +2 -2
- data/lib/constructable/attribute.rb +1 -26
- data/test/constructable/test_attribute.rb +0 -35
- data/test/constructable/test_constructable.rb +2 -2
- data/test/constructable/test_constructor.rb +9 -9
- metadata +3 -3
data/README.markdown
CHANGED
@@ -15,14 +15,14 @@ end
|
|
15
15
|
```
|
16
16
|
|
17
17
|
Then you can construct objects by providing a hash as the last argument
|
18
|
-
to ProgrammingLanguage.new like this:
|
18
|
+
to ```ProgrammingLanguage.new``` like this:
|
19
19
|
|
20
20
|
```ruby
|
21
21
|
ruby = ProgrammingLanguage.new(name: 'Ruby', creator: 'Yukihiro Matsumoto')
|
22
22
|
```
|
23
23
|
|
24
|
-
The object
|
25
|
-
|
24
|
+
The object ```ruby``` will now have the instance variables ```@name``` and
|
25
|
+
```@creator``` set to ```'Ruby'``` and ```'Yukihiro Matsumoto'```.
|
26
26
|
|
27
27
|
|
28
28
|
## Setters, Getters
|
@@ -80,12 +80,7 @@ turtle.biological_class
|
|
80
80
|
```
|
81
81
|
|
82
82
|
|
83
|
-
##
|
84
|
-
|
85
|
-
You can setup validation for constructable attributes, so the users of
|
86
|
-
your api won't provide weird values or none at all:
|
87
|
-
|
88
|
-
### required
|
83
|
+
## Required attributes
|
89
84
|
|
90
85
|
```ruby
|
91
86
|
class Holidays
|
@@ -96,33 +91,6 @@ summer_holidays = Holidays.new
|
|
96
91
|
# raises AttributeError, ':when is a required attribute'
|
97
92
|
```
|
98
93
|
|
99
|
-
### validate\_type
|
100
|
-
|
101
|
-
```ruby
|
102
|
-
class Conference
|
103
|
-
constructable :attendees, validate_type: Integer
|
104
|
-
end
|
105
|
-
|
106
|
-
euruko = Conference.new('~300') # btw, euruko was really great!
|
107
|
-
# raises AttributeError, ':attendees must be of type Integer'
|
108
|
-
```
|
109
|
-
|
110
|
-
### validate
|
111
|
-
|
112
|
-
```ruby
|
113
|
-
class Farm
|
114
|
-
costructable :animals,
|
115
|
-
validate_type: Array,
|
116
|
-
validate: ->(array_of_animals) do
|
117
|
-
array_of_animals.all? { |animal| animal.is_a?(String)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
big_farm = Farm.new(animals: [:pigs, :cows])
|
122
|
-
# raises AttributeError, ':animals has not passed validation'
|
123
|
-
```
|
124
|
-
|
125
|
-
|
126
94
|
## Convert your attributes
|
127
95
|
|
128
96
|
You can pass a converter as an option for a constructable attribute,
|
@@ -162,15 +130,16 @@ rails.opinionated
|
|
162
130
|
## Redefining setters and getters
|
163
131
|
|
164
132
|
You can redefine the setters and getters provided by the constructable
|
165
|
-
macro and still get all the validations and stuff by calling super
|
133
|
+
macro and still get all the validations and stuff by calling ```super```:
|
166
134
|
|
167
135
|
```ruby
|
168
136
|
class Song
|
169
|
-
constructable :length, accessible: true,
|
137
|
+
constructable :length, accessible: true, required: true
|
170
138
|
|
171
139
|
|
172
140
|
def length=(length)
|
173
|
-
|
141
|
+
case length
|
142
|
+
when /(\d{,2}):(\d{,2})/
|
174
143
|
@length = $1.to_i * 60 + $2.to_i
|
175
144
|
else
|
176
145
|
super
|
@@ -185,17 +154,17 @@ song.length = '1:30'
|
|
185
154
|
song.length
|
186
155
|
#=> 90
|
187
156
|
|
188
|
-
song.length =
|
189
|
-
# raises AttributeError, ':length
|
157
|
+
song.length = nil
|
158
|
+
# raises AttributeError, ':length is a required attribute'
|
190
159
|
|
191
|
-
song = Song.new(name: 'Aaron', length:
|
160
|
+
song = Song.new(name: 'Aaron', length: 190)
|
192
161
|
#=> #<Song:0x0x00000100941528 @length=190 @name="Aaron" @name_history=["Aaron"]>
|
193
162
|
```
|
194
163
|
|
195
164
|
## constructable\_attributes method
|
196
165
|
|
197
166
|
You can all the constructable attributes and their values of your class as a hash,
|
198
|
-
by calling the constructable_attributes method from within an instance
|
167
|
+
by calling the ```constructable_attributes``` method from within an instance
|
199
168
|
of your class:
|
200
169
|
|
201
170
|
```ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/constructable.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{constructable}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Manuel Korfmann"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-07-09}
|
13
13
|
s.description = %q{Makes constructing objects through an attributes hash easier}
|
14
14
|
s.email = %q{manu@korfmann.info}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -1,21 +1,8 @@
|
|
1
1
|
module Constructable
|
2
2
|
class Attribute
|
3
|
-
ATTRIBUTES = [:group, :writable, :readable, :accessible, :required, :
|
3
|
+
ATTRIBUTES = [:group, :writable, :readable, :accessible, :required, :default, :converter]
|
4
4
|
attr_accessor *ATTRIBUTES, :name
|
5
5
|
|
6
|
-
REQUIREMENTS = [
|
7
|
-
{
|
8
|
-
name: :validate_type,
|
9
|
-
message: proc {":#{self.name} must be of type #{self.validate_type}"},
|
10
|
-
check: ->(value) { value.is_a? self.validate_type }
|
11
|
-
},
|
12
|
-
{
|
13
|
-
name: :validate,
|
14
|
-
message: proc {":#{self.name} did not pass validation"},
|
15
|
-
check: ->(value) { self.validate.call(value)}
|
16
|
-
}
|
17
|
-
]
|
18
|
-
|
19
6
|
def initialize(name, options = {})
|
20
7
|
@name = name
|
21
8
|
ATTRIBUTES.each do |attribute|
|
@@ -38,20 +25,8 @@ module Constructable
|
|
38
25
|
(self.name.to_s + '=').to_sym
|
39
26
|
end
|
40
27
|
|
41
|
-
def check_for_requirement(requirement, value)
|
42
|
-
if self.send requirement[:name]
|
43
|
-
unless self.instance_exec(value,&requirement[:check])
|
44
|
-
raise AttributeError, instance_eval(&requirement[:message])
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
private :check_for_requirement
|
49
|
-
|
50
28
|
def process(value)
|
51
29
|
unless value.nil?
|
52
|
-
REQUIREMENTS.each do |requirement|
|
53
|
-
check_for_requirement(requirement, value)
|
54
|
-
end
|
55
30
|
self.converter ? converter.(value) : value
|
56
31
|
else
|
57
32
|
raise AttributeError, ":#{self.name} is a required attribute" if self.required
|
@@ -50,41 +50,6 @@ describe 'Attribute' do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe 'validator' do
|
54
|
-
it 'checks for validate_type first' do
|
55
|
-
attribute = Attribute.new(:array, validate_type: Array, validate: ->(value) { value.all? { |s| String === s }})
|
56
|
-
assert_raises AttributeError do
|
57
|
-
attribute.process('obviously not an array')
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'should raise an AttributeError if the validator doesn\'t pass' do
|
62
|
-
attribute = Attribute.new(:foo, validate: ->(number) { number < 5 })
|
63
|
-
begin
|
64
|
-
attribute.process(6)
|
65
|
-
rescue Exception => e
|
66
|
-
assert AttributeError === e, "[#{e.class},#{e.message}] was not expected"
|
67
|
-
assert_equal ':foo did not pass validation', e.message
|
68
|
-
else
|
69
|
-
assert false, 'AttributeError was not raised'
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe 'validate_type check' do
|
75
|
-
it 'should raise an AttributeError if the value has not the wanted validate_type' do
|
76
|
-
attribute = Attribute.new(:foo, validate_type: Integer)
|
77
|
-
begin
|
78
|
-
attribute.process('notanumber')
|
79
|
-
rescue Exception => e
|
80
|
-
assert AttributeError === e, "[#{e.class},#{e.message}] was not expected"
|
81
|
-
assert_equal ':foo must be of type Integer', e.message
|
82
|
-
else
|
83
|
-
assert false, 'AttributeError was not raised'
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
53
|
describe 'default value' do
|
89
54
|
it 'should be possible to provide a default value' do
|
90
55
|
attribute = Attribute.new(:foo, default: ->{ :bar })
|
@@ -7,11 +7,11 @@ describe 'integration' do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'has a nice syntax' do
|
10
|
-
@klass.constructable :foo, :bar, accessible: true,
|
10
|
+
@klass.constructable :foo, :bar, accessible: true, required: true
|
11
11
|
instance = @klass.new(foo: 5, bar: 2)
|
12
12
|
assert_equal 5, instance.foo
|
13
13
|
assert_raises AttributeError do
|
14
|
-
instance.bar =
|
14
|
+
instance.bar = nil
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -14,10 +14,10 @@ describe 'Constructor' do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'defines public setters validating like in the constructor' do
|
17
|
-
@klass.constructable :integer,
|
18
|
-
instance = @klass.new
|
17
|
+
@klass.constructable :integer, required: true, writable: true
|
18
|
+
instance = @klass.new(integer: 1)
|
19
19
|
assert_raises AttributeError do
|
20
|
-
instance.integer =
|
20
|
+
instance.integer = nil
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -25,14 +25,14 @@ describe 'Constructor' do
|
|
25
25
|
|
26
26
|
describe 'class' do
|
27
27
|
it 'getters ' do
|
28
|
-
@klass.constructable :integer,
|
28
|
+
@klass.constructable :integer, accessible: true
|
29
29
|
@klass.class_eval { define_method(:integer){ 1 } }
|
30
30
|
instance = @klass.new(integer: 2)
|
31
31
|
assert_equal 1, instance.integer
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'setters ' do
|
35
|
-
@klass.constructable :integer,
|
35
|
+
@klass.constructable :integer, accessible: true
|
36
36
|
@klass.class_eval { def integer=(foo);@integer = 1;end }
|
37
37
|
instance = @klass.new(integer: 4)
|
38
38
|
instance.integer = 5
|
@@ -42,7 +42,7 @@ describe 'Constructor' do
|
|
42
42
|
|
43
43
|
describe 'module' do
|
44
44
|
before do
|
45
|
-
@module.constructable :integer,
|
45
|
+
@module.constructable :integer, accessible: true
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'getters ' do
|
@@ -74,18 +74,18 @@ describe 'Constructor' do
|
|
74
74
|
|
75
75
|
describe 'allows to super to the generated method' do
|
76
76
|
it 'gets' do
|
77
|
-
@klass.constructable :integer,
|
77
|
+
@klass.constructable :integer, accessible: true
|
78
78
|
@klass.class_eval { def integer; super ;end }
|
79
79
|
instance = @klass.new(integer: 2)
|
80
80
|
assert_equal 2, instance.integer
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'sets' do
|
84
|
-
@klass.constructable :integer,
|
84
|
+
@klass.constructable :integer, required: true, accessible: true
|
85
85
|
@klass.class_eval { def integer=(value); super ;end }
|
86
86
|
instance = @klass.new(integer: 2)
|
87
87
|
assert_raises Constructable::AttributeError do
|
88
|
-
instance.integer =
|
88
|
+
instance.integer = nil
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: constructable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Manuel Korfmann
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-07-09 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -100,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
hash:
|
103
|
+
hash: 4244750192916638565
|
104
104
|
segments:
|
105
105
|
- 0
|
106
106
|
version: "0"
|