attrio 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/attrio.rb CHANGED
@@ -23,16 +23,22 @@ 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)
28
- @@#{options[:as]} ||= {}
29
-
30
- def self.#{options[:as]}(attributes = [])
31
- attributes = Helpers.to_a(attributes).flatten
32
- return @@#{options[:as]} if attributes.empty?
33
-
34
- attributes = @@#{options[:as]}.keys & attributes
35
- @@#{options[:as]}.select{ |k,v| attributes.include?(k) }
26
+
27
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
28
+ @#{options[:as]} ||= {}
29
+
30
+ class << self
31
+ def #{options[:as]}(attributes = [])
32
+ attributes = Helpers.to_a(attributes).flatten
33
+ return @#{options[:as]} if attributes.empty?
34
+
35
+ attributes = @#{options[:as]}.keys & attributes
36
+ @#{options[:as]}.select{ |k,v| attributes.include?(k) }
37
+ end
38
+
39
+ def inherited(subclass)
40
+ subclass.instance_variable_set("@#{options[:as]}", instance_variable_get("@#{options[:as]}").dup)
41
+ end
36
42
  end
37
43
 
38
44
  def #{options[:as]}(attributes = [])
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Attrio
4
4
  class Attribute
5
- attr_reader :klass, :name, :type, :options
5
+ attr_reader :name, :type, :options
6
6
 
7
- def initialize(klass, name, type, options)
8
- @klass = klass; @name = name; @type = type; @options = Helpers.symbolize_hash_keys(options)
7
+ def initialize(name, type, options)
8
+ @name = name; @type = type; @options = Helpers.symbolize_hash_keys(options)
9
9
  end
10
10
 
11
11
  def reader_method_name
@@ -30,13 +30,13 @@ module Attrio
30
30
 
31
31
  def default_value
32
32
  if !defined?(@default_value)
33
- @default_value = Attrio::DefaultValue.new(self.klass, self.name, self.options[:default])
33
+ @default_value = Attrio::DefaultValue.new(self.name, self.options[:default])
34
34
  end
35
35
  @default_value
36
36
  end
37
37
 
38
- def define_writer
39
- Attrio::Builders::WriterBuilder.define(self.klass, self.type,
38
+ def define_writer(klass)
39
+ Attrio::Builders::WriterBuilder.define(klass, self.type,
40
40
  self.options.merge({
41
41
  :method_name => self.writer_method_name,
42
42
  :method_visibility => self.writer_visibility,
@@ -46,8 +46,8 @@ module Attrio
46
46
  self
47
47
  end
48
48
 
49
- def define_reader
50
- Attrio::Builders::ReaderBuilder.define(self.klass, self.type,
49
+ def define_reader(klass)
50
+ Attrio::Builders::ReaderBuilder.define(klass, self.type,
51
51
  self.options.merge({
52
52
  :method_name => self.reader_method_name,
53
53
  :method_visibility => self.reader_visibility,
@@ -4,8 +4,8 @@ module Attrio
4
4
  class AttributesParser
5
5
  attr_reader :klass, :options
6
6
 
7
- def initialize(object, options, &block)
8
- @object = object
7
+ def initialize(klass, options, &block)
8
+ @klass = klass
9
9
  @options = options
10
10
 
11
11
  raise ArgumentError.new('Missing options[:as] value' ) if @options[:as].blank?
@@ -14,16 +14,18 @@ module Attrio
14
14
  end
15
15
 
16
16
  def attr(*args)
17
- attribute_options = (args.last.kind_of?(Hash) ? args.pop : Hash.new)
18
17
  attribute_name = args[0].to_s
18
+ attribute_options = (args.last.kind_of?(Hash) ? args.pop : Hash.new)
19
+ attribute_type = self.fetch_type(attribute_options.delete(:type) || args[1])
19
20
 
20
- type = self.class.cast_type(attribute_options.delete(:type) || args[1])
21
- self.class.const_missing(attribute_options.delete(:type).to_s || args[1].to_s) if type.blank?
22
-
23
- attribute = Attrio::Attribute.new(@object, attribute_name, type, attribute_options).define_writer.define_reader
21
+ attribute = self.create_attribute(attribute_name, attribute_type, attribute_options)
24
22
  self.add_attribute(attribute_name, attribute)
23
+
24
+ self
25
25
  end
26
26
 
27
+ alias_method :attribute, :attr
28
+
27
29
  def self.cast_type(constant)
28
30
  return constant if constant.is_a?(Class) && !!(constant < Attrio::Types::Base)
29
31
 
@@ -49,8 +51,21 @@ module Attrio
49
51
  self.options[:as]
50
52
  end
51
53
 
54
+ def fetch_type(name)
55
+ return if name.nil?
56
+
57
+ type = self.class.cast_type(name)
58
+ self.class.const_missing(name.to_s) if type.blank?
59
+
60
+ type
61
+ end
62
+
63
+ def create_attribute(name, type, options)
64
+ Attrio::Attribute.new(name, type, options).define_writer(self.klass).define_reader(self.klass)
65
+ end
66
+
52
67
  def add_attribute(name, attribute)
53
- @object.send(self.as)[name.to_sym] = attribute
68
+ @klass.send(self.as)[name.to_sym] = attribute
54
69
  end
55
70
  end
56
71
  end
@@ -11,21 +11,30 @@ module Attrio
11
11
 
12
12
  def self.define_accessor(klass, type, options)
13
13
  unless klass.method_defined?(options[:method_name])
14
- klass.send :define_method, options[:method_name] do |value|
15
- if !value.nil?
16
- value = if type.respond_to?(:typecast) && type.respond_to?(:typecasted?)
17
- type.typecasted?(value) ? value : type.typecast(*[value, options])
18
- else
19
- type.new(value)
20
- end
21
- end
22
-
23
- self.instance_variable_set(options[:instance_variable_name], value)
14
+ if type.present?
15
+ self.define_typecasted_method(klass, type, options)
16
+ else
17
+ klass.send :attr_writer, options[:method_name].chop
24
18
  end
25
19
 
26
20
  klass.send options[:method_visibility], options[:method_name]
27
21
  end
28
22
  end
23
+
24
+ def self.define_typecasted_method(klass, type, options)
25
+ klass.send :define_method, options[:method_name] do |value|
26
+ if !value.nil?
27
+ value = if type.respond_to?(:typecast) && type.respond_to?(:typecasted?)
28
+ type.typecasted?(value) ? value : type.typecast(*[value, options])
29
+ else
30
+ type.new(value)
31
+ end
32
+ end
33
+
34
+ self.instance_variable_set(options[:instance_variable_name], value)
35
+ end
36
+ end
29
37
  end
38
+
30
39
  end
31
40
  end
@@ -8,8 +8,8 @@ module Attrio
8
8
  autoload :Symbol, 'attrio/default_value/symbol'
9
9
 
10
10
  class << self
11
- def new(object, attribute, value)
12
- Attrio::DefaultValue::Base.handle(object, attribute, value) || value
11
+ def new(attribute, value)
12
+ Attrio::DefaultValue::Base.handle(attribute, value) || value
13
13
  end
14
14
  end
15
15
  end
@@ -3,20 +3,20 @@
3
3
  module Attrio
4
4
  module DefaultValue
5
5
  class Base
6
- attr_reader :klass, :attribute, :value
6
+ attr_reader :attribute, :value
7
7
 
8
- def self.handle(klass, attribute, value)
8
+ def self.handle(attribute, value)
9
9
  handler = [
10
10
  Attrio::DefaultValue::Callable,
11
11
  Attrio::DefaultValue::Clonable,
12
12
  Attrio::DefaultValue::Symbol
13
13
  ].detect{ |handler| handler.handle?(value) }
14
14
 
15
- handler.new(klass, attribute, value) if handler.present?
15
+ handler.new(attribute, value) if handler.present?
16
16
  end
17
17
 
18
- def initialize(klass, attribute, value)
19
- @klass = klass; @attribute = attribute; @value = value;
18
+ def initialize(attribute, value)
19
+ @attribute = attribute; @value = value;
20
20
  end
21
21
 
22
22
  # Evaluates the value
@@ -3,7 +3,7 @@
3
3
  module Attrio
4
4
  module Version
5
5
  MAJOR = 0
6
- MINOR = 3
6
+ MINOR = 4
7
7
  PATCH = 0
8
8
  BUILD = nil
9
9
 
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Attributes inheritance' do
4
+ before(:all) do
5
+ class Parent
6
+ include Attrio
7
+
8
+ define_attributes do
9
+ attr :email, String
10
+ attr :name, String
11
+ attr :created_at, DateTime, :default => proc{ Time.now }
12
+ end
13
+ end
14
+
15
+ class ChildWithoutAttributes < Parent
16
+ end
17
+
18
+ class ChildWithNewAttributes < Parent
19
+ define_attributes do
20
+ attr :age, Integer
21
+ end
22
+ end
23
+
24
+ class ChildWithOverridenAttributes < Parent
25
+ define_attributes do
26
+ attr :name, Symbol
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'Classes should inherit attributes' do
32
+ context "without attributes" do
33
+ subject { ChildWithoutAttributes.attributes }
34
+
35
+ it "should equal to parent's attributes" do
36
+ should == Parent.attributes
37
+ end
38
+ end
39
+
40
+ context "with new attributes" do
41
+ subject { ChildWithNewAttributes.attributes }
42
+
43
+ it "should include parent's attributes" do
44
+ should include(Parent.attributes)
45
+ end
46
+ end
47
+
48
+ context "with overriden attributes" do
49
+ subject { ChildWithOverridenAttributes.attributes }
50
+
51
+ it "should include not overriden attributes" do
52
+ should include(Parent.attributes.reject { |k| k == :name })
53
+ end
54
+
55
+ it "should include overriden attributes" do
56
+ should include(:name)
57
+ end
58
+
59
+ it "should include overriden attributes with corect options" do
60
+ subject[:name].type.should == Attrio::Types::Symbol
61
+ end
62
+ end
63
+ end
64
+ end
@@ -3,6 +3,7 @@ require 'spec_helper'
3
3
  describe Attrio do
4
4
  let(:model) do
5
5
  attributes_name = self.respond_to?(:attributes_name) ? self.attributes_name : 'attributes'
6
+
6
7
  Class.new do
7
8
  include Attrio
8
9
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Attrio::DefaultValue::Callable do
4
- subject { described_class.new(object, attribute, default_value) }
4
+ subject { described_class.new(attribute, default_value) }
5
5
 
6
6
  let(:model) do
7
7
  Class.new do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Attrio::DefaultValue::Clonable do
4
- subject { described_class.new(object, attribute, default_value) }
4
+ subject { described_class.new(attribute, default_value) }
5
5
 
6
6
  let(:model) do
7
7
  Class.new do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Attrio::DefaultValue::Base, '.handle' do
4
- subject { described_class.handle(mock('object'), mock('attribute'), default) }
4
+ subject { described_class.handle(mock('attribute'), default) }
5
5
 
6
6
  context 'when default is a symbol' do
7
7
  let(:default) { :symbol }
File without changes
File without changes
File without changes
File without changes
@@ -7,11 +7,11 @@ describe Attrio::Types::Base do
7
7
 
8
8
  define_attributes do
9
9
  attr :type_as_constant, Integer
10
- attr :type_in_options_as_constant, Integer
10
+ attr :type_in_options_as_constant, :type => Integer
11
11
  attr :type_as_string, 'integer'
12
- attr :type_in_options_as_string, 'integer'
12
+ attr :type_in_options_as_string, :type => 'integer'
13
13
  attr :type_as_symbol, :integer
14
- attr :type_in_options_as_symbol, :integer
14
+ attr :type_in_options_as_symbol, :type => :integer
15
15
  end
16
16
  end
17
17
  end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
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.3.0
4
+ version: 0.4.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-05 00:00:00.000000000 Z
13
+ date: 2013-06-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
17
- requirement: !ruby/object:Gem::Requirement
17
+ requirement: &70339309557080 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,15 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
28
- - - ! '>='
29
- - !ruby/object:Gem::Version
30
- version: '0'
25
+ version_requirements: *70339309557080
31
26
  - !ruby/object:Gem::Dependency
32
27
  name: webmock
33
- requirement: !ruby/object:Gem::Requirement
28
+ requirement: &70339309556540 !ruby/object:Gem::Requirement
34
29
  none: false
35
30
  requirements:
36
31
  - - ~>
@@ -38,15 +33,10 @@ dependencies:
38
33
  version: 1.9.0
39
34
  type: :development
40
35
  prerelease: false
41
- version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
44
- - - ~>
45
- - !ruby/object:Gem::Version
46
- version: 1.9.0
36
+ version_requirements: *70339309556540
47
37
  - !ruby/object:Gem::Dependency
48
38
  name: simplecov
49
- requirement: !ruby/object:Gem::Requirement
39
+ requirement: &70339309572460 !ruby/object:Gem::Requirement
50
40
  none: false
51
41
  requirements:
52
42
  - - ! '>='
@@ -54,15 +44,10 @@ dependencies:
54
44
  version: '0'
55
45
  type: :development
56
46
  prerelease: false
57
- version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
- requirements:
60
- - - ! '>='
61
- - !ruby/object:Gem::Version
62
- version: '0'
47
+ version_requirements: *70339309572460
63
48
  - !ruby/object:Gem::Dependency
64
49
  name: coveralls
65
- requirement: !ruby/object:Gem::Requirement
50
+ requirement: &70339309572000 !ruby/object:Gem::Requirement
66
51
  none: false
67
52
  requirements:
68
53
  - - ! '>='
@@ -70,15 +55,10 @@ dependencies:
70
55
  version: '0'
71
56
  type: :development
72
57
  prerelease: false
73
- version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
- requirements:
76
- - - ! '>='
77
- - !ruby/object:Gem::Version
78
- version: '0'
58
+ version_requirements: *70339309572000
79
59
  - !ruby/object:Gem::Dependency
80
60
  name: rake
81
- requirement: !ruby/object:Gem::Requirement
61
+ requirement: &70339309571560 !ruby/object:Gem::Requirement
82
62
  none: false
83
63
  requirements:
84
64
  - - ! '>='
@@ -86,15 +66,10 @@ dependencies:
86
66
  version: '0'
87
67
  type: :development
88
68
  prerelease: false
89
- version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
- requirements:
92
- - - ! '>='
93
- - !ruby/object:Gem::Version
94
- version: '0'
69
+ version_requirements: *70339309571560
95
70
  - !ruby/object:Gem::Dependency
96
71
  name: bundler
97
- requirement: !ruby/object:Gem::Requirement
72
+ requirement: &70339309571120 !ruby/object:Gem::Requirement
98
73
  none: false
99
74
  requirements:
100
75
  - - ! '>='
@@ -102,12 +77,7 @@ dependencies:
102
77
  version: '0'
103
78
  type: :development
104
79
  prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
- requirements:
108
- - - ! '>='
109
- - !ruby/object:Gem::Version
110
- version: '0'
80
+ version_requirements: *70339309571120
111
81
  description:
112
82
  email: hello@jetrockets.ru
113
83
  executables: []
@@ -148,24 +118,25 @@ files:
148
118
  - lib/attrio/types/symbol.rb
149
119
  - lib/attrio/types/time.rb
150
120
  - lib/attrio/version.rb
151
- - spec/attrio/attrio_spec.rb
152
- - spec/attrio/default_value/callable_spec.rb
153
- - spec/attrio/default_value/clonable_spec.rb
154
- - spec/attrio/default_value/handle_spec.rb
155
- - spec/attrio/default_value/symbol_spec.rb
156
- - spec/attrio/default_value/value_spec.rb
157
- - spec/attrio/embed_value_spec.rb
158
- - spec/attrio/inspect_spec.rb
159
- - spec/attrio/reset_spec.rb
160
- - spec/attrio/type_spec.rb
161
- - spec/attrio/types/boolean_spec.rb
162
- - spec/attrio/types/date_spec.rb
163
- - spec/attrio/types/date_time_spec.rb
164
- - spec/attrio/types/float_spec.rb
165
- - spec/attrio/types/integer_spec.rb
166
- - spec/attrio/types/symbol_spec.rb
167
- - spec/attrio/types/time_spec.rb
121
+ - spec/integration/embedded_value_spec.rb
122
+ - spec/integration/inheritance_spec.rb
168
123
  - spec/spec_helper.rb
124
+ - spec/unit/attrio_spec.rb
125
+ - spec/unit/default_value/callable_spec.rb
126
+ - spec/unit/default_value/clonable_spec.rb
127
+ - spec/unit/default_value/handle_spec.rb
128
+ - spec/unit/default_value/symbol_spec.rb
129
+ - spec/unit/default_value/value_spec.rb
130
+ - spec/unit/inspect_spec.rb
131
+ - spec/unit/reset_spec.rb
132
+ - spec/unit/type_spec.rb
133
+ - spec/unit/types/boolean_spec.rb
134
+ - spec/unit/types/date_spec.rb
135
+ - spec/unit/types/date_time_spec.rb
136
+ - spec/unit/types/float_spec.rb
137
+ - spec/unit/types/integer_spec.rb
138
+ - spec/unit/types/symbol_spec.rb
139
+ - spec/unit/types/time_spec.rb
169
140
  homepage: https://github.com/jetrockets/attrio
170
141
  licenses: []
171
142
  post_install_message:
@@ -180,7 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
180
151
  version: '0'
181
152
  segments:
182
153
  - 0
183
- hash: -2263639350992331288
154
+ hash: 2234961798158657284
184
155
  required_rubygems_version: !ruby/object:Gem::Requirement
185
156
  none: false
186
157
  requirements:
@@ -189,30 +160,31 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
160
  version: '0'
190
161
  segments:
191
162
  - 0
192
- hash: -2263639350992331288
163
+ hash: 2234961798158657284
193
164
  requirements: []
194
165
  rubyforge_project:
195
- rubygems_version: 1.8.24
166
+ rubygems_version: 1.8.15
196
167
  signing_key:
197
168
  specification_version: 3
198
169
  summary: Attributes for plain old Ruby objects. No dependencies, only simplicity and
199
170
  clearness.
200
171
  test_files:
201
- - spec/attrio/attrio_spec.rb
202
- - spec/attrio/default_value/callable_spec.rb
203
- - spec/attrio/default_value/clonable_spec.rb
204
- - spec/attrio/default_value/handle_spec.rb
205
- - spec/attrio/default_value/symbol_spec.rb
206
- - spec/attrio/default_value/value_spec.rb
207
- - spec/attrio/embed_value_spec.rb
208
- - spec/attrio/inspect_spec.rb
209
- - spec/attrio/reset_spec.rb
210
- - spec/attrio/type_spec.rb
211
- - spec/attrio/types/boolean_spec.rb
212
- - spec/attrio/types/date_spec.rb
213
- - spec/attrio/types/date_time_spec.rb
214
- - spec/attrio/types/float_spec.rb
215
- - spec/attrio/types/integer_spec.rb
216
- - spec/attrio/types/symbol_spec.rb
217
- - spec/attrio/types/time_spec.rb
172
+ - spec/integration/embedded_value_spec.rb
173
+ - spec/integration/inheritance_spec.rb
218
174
  - spec/spec_helper.rb
175
+ - spec/unit/attrio_spec.rb
176
+ - spec/unit/default_value/callable_spec.rb
177
+ - spec/unit/default_value/clonable_spec.rb
178
+ - spec/unit/default_value/handle_spec.rb
179
+ - spec/unit/default_value/symbol_spec.rb
180
+ - spec/unit/default_value/value_spec.rb
181
+ - spec/unit/inspect_spec.rb
182
+ - spec/unit/reset_spec.rb
183
+ - spec/unit/type_spec.rb
184
+ - spec/unit/types/boolean_spec.rb
185
+ - spec/unit/types/date_spec.rb
186
+ - spec/unit/types/date_time_spec.rb
187
+ - spec/unit/types/float_spec.rb
188
+ - spec/unit/types/integer_spec.rb
189
+ - spec/unit/types/symbol_spec.rb
190
+ - spec/unit/types/time_spec.rb