attrio 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -3,6 +3,5 @@ rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
5
  - 2.0.0
6
- - ruby-head
7
6
  - rbx-19mode
8
7
  - jruby-19mode
data/README.md CHANGED
@@ -300,6 +300,23 @@ class Klass
300
300
  end
301
301
  ```
302
302
 
303
+ **Array**
304
+
305
+ Arrays are designed to automatically handle collections of objects (that also can be typecasted)
306
+
307
+ If value that should be typecasted responds to `split`, then this method is called with default (or overriden) attributes, else `Array` is wrapped on value. You can easily handle types and options of collection elements.
308
+
309
+ ```ruby
310
+ class Klass
311
+ include Attrio
312
+
313
+ define_attributes do
314
+ attr :array_attribute, Array
315
+ attr :custom_array_attribute, Array, :split => ', ', :element => { :type => Date, :options => { :format => '%m/%d/%y' } }
316
+ end
317
+ end
318
+ ```
319
+
303
320
  ## Inspect
304
321
  Attrio adds its own `#inspect` method when included to the class. This overridden method prints object attributes in easy to read manner. To disable this feature pass `:inspect => false` to `define_arguments` block.
305
322
 
data/lib/attrio.rb CHANGED
@@ -23,8 +23,8 @@ module Attrio
23
23
  module ClassMethods
24
24
  def define_attributes(options = {}, &block)
25
25
  options[:as] ||= :attributes
26
-
27
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
26
+
27
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
28
28
  @#{options[:as]} ||= {}
29
29
 
30
30
  class << self
@@ -33,10 +33,10 @@ module Attrio
33
33
  return @#{options[:as]} if attributes.empty?
34
34
 
35
35
  attributes = @#{options[:as]}.keys & attributes
36
- @#{options[:as]}.select{ |k,v| attributes.include?(k) }
36
+ @#{options[:as]}.select{ |k,v| attributes.include?(k) }
37
37
  end
38
38
 
39
- def inherited(subclass)
39
+ def inherited(subclass)
40
40
  subclass.instance_variable_set("@#{options[:as]}", instance_variable_get("@#{options[:as]}").dup)
41
41
  end
42
42
  end
@@ -67,6 +67,7 @@ module Attrio
67
67
  end
68
68
 
69
69
  module Types
70
+ autoload :Array, 'attrio/types/array'
70
71
  autoload :Base, 'attrio/types/base'
71
72
  autoload :Boolean, 'attrio/types/boolean'
72
73
  autoload :Date, 'attrio/types/date'
@@ -32,7 +32,7 @@ module Attrio
32
32
  if !defined?(@default_value)
33
33
  @default_value = Attrio::DefaultValue.new(self.name, self.options[:default])
34
34
  end
35
- @default_value
35
+ @default_value
36
36
  end
37
37
 
38
38
  def define_writer(klass)
@@ -64,7 +64,7 @@ module Attrio
64
64
  end
65
65
 
66
66
  def accessor_visibility_from_options(accessor)
67
- return self.options[accessor] if self.options[accessor].present? && [:public, :protected, :private].include?(self.options[accessor])
67
+ return self.options[accessor] if self.options[accessor].present? && [:public, :protected, :private].include?(self.options[accessor])
68
68
  (self.options[accessor].is_a?(Hash) && self.options[accessor][:visibility]) || self.options["#{accessor.to_s}_visibility".to_sym]
69
69
  end
70
70
  end
@@ -31,7 +31,7 @@ module Attrio
31
31
 
32
32
  string = constant.to_s
33
33
  string = string.camelize if (string =~ /\w_\w/ || string.chars.first.downcase == string.chars.first)
34
-
34
+
35
35
  begin
36
36
  if Attrio::Types.const_defined?(string)
37
37
  return Attrio::Types.const_get(string)
@@ -66,6 +66,6 @@ module Attrio
66
66
 
67
67
  def add_attribute(name, attribute)
68
68
  @klass.send(self.as)[name.to_sym] = attribute
69
- end
69
+ end
70
70
  end
71
71
  end
@@ -16,10 +16,10 @@ module Attrio
16
16
  else
17
17
  klass.send :attr_writer, options[:method_name].chop
18
18
  end
19
-
19
+
20
20
  klass.send options[:method_visibility], options[:method_name]
21
- end
22
- end
21
+ end
22
+ end
23
23
 
24
24
  def self.define_typecasting_method(klass, type, options)
25
25
  klass.send :define_method, options[:method_name] do |value|
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ module Attrio
4
+ module Types
5
+ class Array < Base
6
+ def self.typecast(value, options = {})
7
+ begin
8
+ array = value.respond_to?(:split) ? value.split(options[:split]) : Attrio::Helpers.to_a(value)
9
+
10
+ if options[:element].present?
11
+ type = Attrio::AttributesParser.cast_type(self.element_type(options[:element]))
12
+ options = self.element_options(options[:element])
13
+
14
+ array.map! do |item|
15
+ if type.respond_to?(:typecast) && type.respond_to?(:typecasted?)
16
+ type.typecasted?(item) ? item : type.typecast(*[item, options])
17
+ else
18
+ type == Hash && item.is_a?(Hash) ? value : type.new(item)
19
+ end
20
+ end
21
+ end
22
+
23
+ array
24
+ rescue ArgumentError => e
25
+ nil
26
+ end
27
+ end
28
+
29
+ def self.typecasted?(value)
30
+ value.is_a? ::Array
31
+ end
32
+
33
+ protected
34
+
35
+ def self.element_type(element)
36
+ element[:type]
37
+ rescue
38
+ element
39
+ end
40
+
41
+ def self.element_options(element)
42
+ element[:options]
43
+ rescue
44
+ {}
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- module Attrio
3
+ module Attrio
4
4
  module Types
5
5
  class Boolean < Base
6
6
  def self.typecast(value, options = {})
@@ -1,10 +1,10 @@
1
1
  # encoding: utf-8
2
2
 
3
- module Attrio
3
+ module Attrio
4
4
  module Version
5
5
  MAJOR = 0
6
- MINOR = 4
7
- PATCH = 1
6
+ MINOR = 5
7
+ PATCH = 0
8
8
  BUILD = nil
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe Attrio::Types::Array do
4
+ context 'standard casting conventions' do
5
+ let(:model) do
6
+ Class.new do
7
+ include Attrio
8
+
9
+ define_attributes do
10
+ attr :array_attribute, Array
11
+ end
12
+ end
13
+ end
14
+
15
+ let(:object){ model.new }
16
+
17
+ context 'with not typecasted assignment' do
18
+ it 'should cast space separated string' do
19
+ object.array_attribute = 'first second third'
20
+ object.array_attribute.should be_instance_of(Array)
21
+ object.array_attribute.should == %w(first second third)
22
+ end
23
+ end
24
+
25
+ context 'with typecasted assignment' do
26
+ it 'should assign <Array>' do
27
+ array = %w(first second third)
28
+
29
+ object.array_attribute = array
30
+ object.array_attribute.should be_instance_of(Array)
31
+ object.array_attribute.should be_equal(array)
32
+ end
33
+ end
34
+ end
35
+
36
+ context 'overriden split and element type' do
37
+ let(:model) do
38
+ Class.new do
39
+ include Attrio
40
+
41
+ define_attributes do
42
+ attr :array_attribute, Array, :split => ', ', :element => { :type => Date, :options => { :format => '%m/%d/%y' } }
43
+ end
44
+ end
45
+ end
46
+
47
+ let(:object){ model.new }
48
+
49
+ context 'with not typecasted assignment' do
50
+ it 'should cast space separated string' do
51
+ dates = [Date.today, (Date.today + 1), (Date.today + 2)]
52
+ string = dates.map{ |date| date.strftime('%m/%d/%y') }.join(', ')
53
+
54
+ object.array_attribute = string
55
+ object.array_attribute.should be_instance_of(Array)
56
+ object.array_attribute.should == dates
57
+ end
58
+ end
59
+ end
60
+ end
@@ -14,55 +14,55 @@ describe Attrio::Types::Boolean do
14
14
 
15
15
  let(:object){ model.new }
16
16
 
17
- context 'not typecasted assignment' do
18
- it 'should cast "true"' do
17
+ context 'with not typecasted assignment' do
18
+ it 'should cast "true"' do
19
19
  object.boolean_attribute = 'true'
20
20
  object.boolean_attribute?.should be_true
21
21
  end
22
22
 
23
- it 'should cast "1"' do
23
+ it 'should cast "1"' do
24
24
  object.boolean_attribute = '1'
25
25
  object.boolean_attribute?.should be_true
26
26
  end
27
27
 
28
- it 'should cast 1' do
28
+ it 'should cast 1' do
29
29
  object.boolean_attribute = 1
30
30
  object.boolean_attribute?.should be_true
31
31
  end
32
32
 
33
- it 'should cast "yes"' do
33
+ it 'should cast "yes"' do
34
34
  object.boolean_attribute = 'yes'
35
35
  object.boolean_attribute?.should be_true
36
36
  end
37
37
 
38
- it 'should cast "false"' do
38
+ it 'should cast "false"' do
39
39
  object.boolean_attribute = 'false'
40
40
  object.boolean_attribute?.should be_false
41
41
  end
42
42
 
43
- it 'should cast "0"' do
43
+ it 'should cast "0"' do
44
44
  object.boolean_attribute = '0'
45
45
  object.boolean_attribute?.should be_false
46
46
  end
47
47
 
48
- it 'should cast 0' do
48
+ it 'should cast 0' do
49
49
  object.boolean_attribute = 0
50
50
  object.boolean_attribute?.should be_false
51
51
  end
52
52
 
53
- it 'should cast "no"' do
53
+ it 'should cast "no"' do
54
54
  object.boolean_attribute = 'no'
55
55
  object.boolean_attribute?.should be_false
56
56
  end
57
57
  end
58
58
 
59
- context 'typecasted assignment' do
60
- it 'should assign <TrueClass> and do not typecast' do
59
+ context 'with typecasted assignment' do
60
+ it 'should assign <TrueClass> and do not typecast' do
61
61
  object.boolean_attribute = true
62
62
  object.boolean_attribute?.should be_true
63
63
  end
64
64
 
65
- it 'should assign <FalseClass> and do not typecast' do
65
+ it 'should assign <FalseClass> and do not typecast' do
66
66
  object.boolean_attribute = false
67
67
  object.boolean_attribute?.should be_false
68
68
  end
@@ -82,12 +82,12 @@ describe Attrio::Types::Boolean do
82
82
 
83
83
  let(:object){ model.new }
84
84
 
85
- it 'should cast "yeah" as TrueClass' do
85
+ it 'should cast "yeah" as TrueClass' do
86
86
  object.boolean_attribute = 'yeah'
87
87
  object.boolean_attribute?.should be_true
88
88
  end
89
89
 
90
- it 'should cast anything else as FalseClass' do
90
+ it 'should cast anything else as FalseClass' do
91
91
  object.boolean_attribute = 'yes'
92
92
  object.boolean_attribute?.should be_false
93
93
 
@@ -97,5 +97,5 @@ describe Attrio::Types::Boolean do
97
97
  object.boolean_attribute = 0
98
98
  object.boolean_attribute?.should be_false
99
99
  end
100
- end
100
+ end
101
101
  end
@@ -13,7 +13,7 @@ describe Attrio::Types::Date do
13
13
  end
14
14
 
15
15
  let(:object){ model.new }
16
-
16
+
17
17
  context 'with not typecasted assignment' do
18
18
  it 'should cast <String>' do
19
19
  today = Date.today
@@ -47,7 +47,7 @@ describe Attrio::Types::Date do
47
47
  end
48
48
 
49
49
  let(:object){ model.new }
50
-
50
+
51
51
  context 'with not typecasted assignment' do
52
52
  it 'should cast <String> of appropriate format' do
53
53
  today = Date.today
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attrio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-06-27 00:00:00.000000000 Z
13
+ date: 2013-07-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
17
- requirement: &70232928034320 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,15 @@ dependencies:
22
22
  version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *70232928034320
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: webmock
28
- requirement: &70232928033780 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ~>
@@ -33,10 +38,15 @@ dependencies:
33
38
  version: 1.9.0
34
39
  type: :development
35
40
  prerelease: false
36
- version_requirements: *70232928033780
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 1.9.0
37
47
  - !ruby/object:Gem::Dependency
38
48
  name: simplecov
39
- requirement: &70232928033240 !ruby/object:Gem::Requirement
49
+ requirement: !ruby/object:Gem::Requirement
40
50
  none: false
41
51
  requirements:
42
52
  - - ! '>='
@@ -44,10 +54,15 @@ dependencies:
44
54
  version: '0'
45
55
  type: :development
46
56
  prerelease: false
47
- version_requirements: *70232928033240
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
48
63
  - !ruby/object:Gem::Dependency
49
64
  name: coveralls
50
- requirement: &70232928032580 !ruby/object:Gem::Requirement
65
+ requirement: !ruby/object:Gem::Requirement
51
66
  none: false
52
67
  requirements:
53
68
  - - ! '>='
@@ -55,10 +70,15 @@ dependencies:
55
70
  version: '0'
56
71
  type: :development
57
72
  prerelease: false
58
- version_requirements: *70232928032580
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
59
79
  - !ruby/object:Gem::Dependency
60
80
  name: rake
61
- requirement: &70232928048240 !ruby/object:Gem::Requirement
81
+ requirement: !ruby/object:Gem::Requirement
62
82
  none: false
63
83
  requirements:
64
84
  - - ! '>='
@@ -66,10 +86,15 @@ dependencies:
66
86
  version: '0'
67
87
  type: :development
68
88
  prerelease: false
69
- version_requirements: *70232928048240
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
70
95
  - !ruby/object:Gem::Dependency
71
96
  name: bundler
72
- requirement: &70232928046760 !ruby/object:Gem::Requirement
97
+ requirement: !ruby/object:Gem::Requirement
73
98
  none: false
74
99
  requirements:
75
100
  - - ! '>='
@@ -77,7 +102,12 @@ dependencies:
77
102
  version: '0'
78
103
  type: :development
79
104
  prerelease: false
80
- version_requirements: *70232928046760
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
81
111
  description:
82
112
  email: hello@jetrockets.ru
83
113
  executables: []
@@ -109,6 +139,7 @@ files:
109
139
  - lib/attrio/initialize.rb
110
140
  - lib/attrio/inspect.rb
111
141
  - lib/attrio/reset.rb
142
+ - lib/attrio/types/array.rb
112
143
  - lib/attrio/types/base.rb
113
144
  - lib/attrio/types/boolean.rb
114
145
  - lib/attrio/types/date.rb
@@ -130,6 +161,7 @@ files:
130
161
  - spec/unit/inspect_spec.rb
131
162
  - spec/unit/reset_spec.rb
132
163
  - spec/unit/type_spec.rb
164
+ - spec/unit/types/array_spec.rb
133
165
  - spec/unit/types/boolean_spec.rb
134
166
  - spec/unit/types/date_spec.rb
135
167
  - spec/unit/types/date_time_spec.rb
@@ -151,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
183
  version: '0'
152
184
  segments:
153
185
  - 0
154
- hash: 1677394698442050783
186
+ hash: -10874694009707771
155
187
  required_rubygems_version: !ruby/object:Gem::Requirement
156
188
  none: false
157
189
  requirements:
@@ -160,10 +192,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
192
  version: '0'
161
193
  segments:
162
194
  - 0
163
- hash: 1677394698442050783
195
+ hash: -10874694009707771
164
196
  requirements: []
165
197
  rubyforge_project:
166
- rubygems_version: 1.8.15
198
+ rubygems_version: 1.8.24
167
199
  signing_key:
168
200
  specification_version: 3
169
201
  summary: Attributes for plain old Ruby objects. No dependencies, only simplicity and
@@ -181,6 +213,7 @@ test_files:
181
213
  - spec/unit/inspect_spec.rb
182
214
  - spec/unit/reset_spec.rb
183
215
  - spec/unit/type_spec.rb
216
+ - spec/unit/types/array_spec.rb
184
217
  - spec/unit/types/boolean_spec.rb
185
218
  - spec/unit/types/date_spec.rb
186
219
  - spec/unit/types/date_time_spec.rb