attrio 0.4.1 → 0.5.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/.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