virtus 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/History.md CHANGED
@@ -1,4 +1,13 @@
1
- # v0.0.6 to-be-released
1
+ # v0.0.7 to-be-released
2
+
3
+ * [BREAKING CHANGE] Attribute.primitive? has been removed (solnic)
4
+ * [fixed] Added missing coercion_method setting to Virtus::Attribute::Object (solnic)
5
+ * [general] Default value logic has been extracted into Attribute::DefaultValue class (solnic)
6
+ * [added] Virtus::Attribute::Class (solnic)
7
+
8
+ [Compare v0.0.5..master](https://github.com/solnic/virtus/compare/v0.0.5...master)
9
+
10
+ # v0.0.6 2011-07-31
2
11
 
3
12
  * [BREAKING CHANGE] Moved Virtus.determine_type to a shared module Virtus::TypeLookup (dkubb)
4
13
  * [BREAKING CHANGE] Attribute#typecast_to_primitive has been replaced by Attribute#coerce (solnic)
@@ -10,7 +19,7 @@
10
19
  * [changed] Typecast classes have been replace by a new hierarchy of Coercion classes like Coercion::String, Coercion::Integer etc. (solnic)
11
20
  * [changed] Attribute#get, #get!, #set, #set! & #coerce are now part of the public API (solnic)
12
21
 
13
- [Compare v0.0.5..master](https://github.com/solnic/virtus/compare/v0.0.5...master)
22
+ [Compare v0.0.5..v0.0.6](https://github.com/solnic/virtus/compare/v0.0.5...v0.0.6)
14
23
 
15
24
  # v0.0.5 2011-07-10
16
25
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.7
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 20
3
- total_score: 268
3
+ total_score: 264
data/config/roodi.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- AbcMetricMethodCheck: { score: 8.1 }
2
+ AbcMetricMethodCheck: { score: 10.1 }
3
3
  AssignmentInConditionalCheck: { }
4
4
  CaseMissingElseCheck: { }
5
5
  ClassLineCountCheck: { line_count: 309 }
@@ -0,0 +1,21 @@
1
+ module Virtus
2
+ class Attribute
3
+
4
+ # Class
5
+ #
6
+ # @example
7
+ # class Entity
8
+ # include Virtus
9
+ #
10
+ # attribute :type, Class
11
+ # end
12
+ #
13
+ # post = Entity.new(:model => Model)
14
+ #
15
+ class Class < Object
16
+ primitive ::Class
17
+ coercion_method :to_class
18
+
19
+ end # class Class
20
+ end # class Attribute
21
+ end # module Virtus
@@ -0,0 +1,71 @@
1
+ module Virtus
2
+ class Attribute
3
+
4
+ # Class representing the default value option
5
+ class DefaultValue
6
+ DUP_CLASSES = [ ::NilClass, ::TrueClass, ::FalseClass,
7
+ ::Numeric, ::Symbol ].freeze
8
+
9
+ # Returns the attribute associated with this default value instance
10
+ #
11
+ # @return [Virtus::Attribute::Object]
12
+ #
13
+ # @api private
14
+ attr_reader :attribute
15
+
16
+ # Returns the value instance
17
+ #
18
+ # @return [Object]
19
+ #
20
+ # @api private
21
+ attr_reader :value
22
+
23
+ # Initializes an default value instance
24
+ #
25
+ # @param [Virtus::Attribute] attribute
26
+ # @param [Object] value
27
+ #
28
+ # @return [undefined]
29
+ #
30
+ # @api private
31
+ def initialize(attribute, value)
32
+ @attribute = attribute
33
+ @value = case value when *DUP_CLASSES then value else value.dup end
34
+ end
35
+
36
+ # Evaluates the value
37
+ #
38
+ # @param [Object]
39
+ #
40
+ # @return [Object] evaluated value
41
+ #
42
+ # @api private
43
+ def evaluate(instance)
44
+ callable? ? call(instance) : value
45
+ end
46
+
47
+ private
48
+
49
+ # Evaluates a proc value
50
+ #
51
+ # @param [Object]
52
+ #
53
+ # @return [Object] evaluated value
54
+ #
55
+ # @api private
56
+ def call(instance)
57
+ value.call(instance, attribute)
58
+ end
59
+
60
+ # Returns if the value is callable
61
+ #
62
+ # @return [TrueClass,FalseClass]
63
+ #
64
+ # @api private
65
+ def callable?
66
+ value.respond_to?(:call)
67
+ end
68
+
69
+ end # class DefaultValue
70
+ end # class Attribute
71
+ end # module Virtus
@@ -3,7 +3,8 @@ module Virtus
3
3
 
4
4
  # Base class for every attribute
5
5
  class Object < Attribute
6
- primitive ::Object
6
+ primitive ::Object
7
+ coercion_method :to_object
7
8
 
8
9
  end # class Object
9
10
  end # class Attribute
@@ -8,18 +8,6 @@ module Virtus
8
8
  extend TypeLookup
9
9
  extend Options
10
10
 
11
- # Returns if the given value's class is an attribute's primitive
12
- #
13
- # @example
14
- # Virtus::Attribute::String.primitive?('String') # => true
15
- #
16
- # @return [Boolean]
17
- #
18
- # @api public
19
- def self.primitive?(value)
20
- value.kind_of?(primitive)
21
- end
22
-
23
11
  # Returns name of the attribute
24
12
  #
25
13
  # @example
@@ -96,8 +84,8 @@ module Virtus
96
84
 
97
85
  @instance_variable_name = "@#{@name}".freeze
98
86
  @coercion_method = @options.fetch(:coercion_method)
87
+ @default = DefaultValue.new(self, @options[:default])
99
88
 
100
- set_default
101
89
  set_visibility
102
90
  end
103
91
 
@@ -130,7 +118,7 @@ module Virtus
130
118
  if instance.instance_variable_defined?(instance_variable_name)
131
119
  get!(instance)
132
120
  else
133
- set_default_value(instance)
121
+ set!(instance, default.evaluate(instance))
134
122
  end
135
123
  end
136
124
 
@@ -223,18 +211,6 @@ module Virtus
223
211
 
224
212
  private
225
213
 
226
- # Sets a default value
227
- #
228
- # @param [Object]
229
- #
230
- # @return [Object]
231
- # default value that was set
232
- #
233
- # @api private
234
- def set_default_value(instance)
235
- set!(instance, default.kind_of?(Proc) ? default.call(instance, self) : default)
236
- end
237
-
238
214
  # Sets visibility of reader/write methods based on the options hash
239
215
  #
240
216
  # @return [undefined]
@@ -246,21 +222,5 @@ module Virtus
246
222
  @writer_visibility = @options.fetch(:writer, default_accessor)
247
223
  end
248
224
 
249
- # Sets default value option
250
- #
251
- # @return [Object]
252
- #
253
- # @api private
254
- def set_default
255
- default = @options[:default]
256
-
257
- @default = case default
258
- when Proc, ::NilClass, ::TrueClass, ::FalseClass, ::Numeric, ::Symbol
259
- default
260
- else
261
- default.dup
262
- end
263
- end
264
-
265
225
  end # class Attribute
266
226
  end # module Virtus
@@ -11,6 +11,21 @@ module Virtus
11
11
 
12
12
  NUMERIC_REGEXP = /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/.freeze
13
13
 
14
+ # Coerce give value to a constant
15
+ #
16
+ # @example
17
+ # Virtus::Coercion::String.to_class('String') # => String
18
+ #
19
+ # @param [String] value
20
+ #
21
+ # @return [Object]
22
+ #
23
+ # @api public
24
+ def self.to_class(value)
25
+ # TODO: add support for namespaced classes like 'Virtus::Attribute::String'
26
+ ::Object.const_get(value)
27
+ end
28
+
14
29
  # Coerce given value to Time
15
30
  #
16
31
  # @example
@@ -117,7 +117,20 @@ module Virtus
117
117
  end
118
118
  end
119
119
 
120
- # @see Virtus::InstanceMethods#attributes
120
+ # Returns a hash of all publicly accessible attributes
121
+ #
122
+ # @example
123
+ # class User
124
+ # include Virtus
125
+ #
126
+ # attribute :name, String
127
+ # attribute :age, Integer
128
+ # end
129
+ #
130
+ # user = User.new(:name => 'John', :age => 28)
131
+ # user.attributes # => { :name => 'John', :age => 28 }
132
+ #
133
+ # @return [Hash]
121
134
  #
122
135
  # @api public
123
136
  def to_hash
data/lib/virtus.rb CHANGED
@@ -51,8 +51,10 @@ require 'virtus/coercion/time'
51
51
  require 'virtus/coercion/string'
52
52
  require 'virtus/coercion/symbol'
53
53
 
54
+ require 'virtus/attribute/default_value'
54
55
  require 'virtus/attribute'
55
56
  require 'virtus/attribute/object'
57
+ require 'virtus/attribute/class'
56
58
  require 'virtus/attribute/array'
57
59
  require 'virtus/attribute/boolean'
58
60
  require 'virtus/attribute/date'
@@ -5,6 +5,13 @@ describe Virtus::ClassMethods, '.attribute' do
5
5
  Class.new { include Virtus }
6
6
  end
7
7
 
8
+ (Virtus::Attribute.descendants + [Virtus::Attribute::Object]).each do |attribute_class|
9
+ context "with #{attribute_class.inspect}" do
10
+ subject { described_class.attribute(:name, attribute_class) }
11
+ specify { subject.attributes[:name].should be_instance_of(attribute_class) }
12
+ end
13
+ end
14
+
8
15
  specify { described_class.should respond_to(:attribute) }
9
16
 
10
17
  context "in the class" do
@@ -27,7 +27,7 @@ shared_examples_for 'Attribute#get' do
27
27
  end
28
28
 
29
29
  let(:evaluated_proc_value) do
30
- attribute.default.call(instance, attribute)
30
+ attribute.default.evaluate(attribute)
31
31
  end
32
32
 
33
33
  it { should == evaluated_proc_value }
@@ -1,7 +1,6 @@
1
1
  shared_examples_for 'Attribute' do
2
2
  it_behaves_like 'Attribute.accept_options'
3
3
  it_behaves_like 'Attribute.accepted_options'
4
- it_behaves_like 'Attribute.primitive?'
5
4
  it_behaves_like 'Attribute#inspect'
6
5
  it_behaves_like 'Attribute#set'
7
6
  it_behaves_like 'Attribute#get'
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute::Class do
4
+ it_should_behave_like 'Attribute' do
5
+ let(:attribute_name) { :String }
6
+ let(:attribute_value) { String }
7
+ let(:attribute_value_other) { 'String' }
8
+ let(:attribute_default) { 'Object' }
9
+ let(:attribute_default_proc) { lambda { |instance, attribute| attribute.name.to_s } }
10
+ end
11
+
12
+ describe '#coerce' do
13
+ let(:attribute) { described_class.new(:type) }
14
+
15
+ subject { attribute.coerce(value) }
16
+
17
+ context 'with a String' do
18
+ let(:value) { 'String' }
19
+
20
+ it { should be(String) }
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute::DefaultValue, '.new' do
4
+ subject { described_class.new(attribute, value) }
5
+
6
+ let(:attribute) { Virtus::Attribute::String.new(:attribute) }
7
+
8
+ context 'with a value that can be duped' do
9
+ let(:value) { 'something' }
10
+
11
+ its(:value) { should eql(value) }
12
+ its(:value) { should_not equal(value) }
13
+ end
14
+
15
+ context 'with a value that cannot be duped' do
16
+ [ nil, true, false, 1, :symbol ].each do |value|
17
+ context "with #{value.inspect}" do
18
+ let(:value) { value }
19
+
20
+ its(:value) { should equal(value) }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Attribute::DefaultValue, '#evaluate' do
4
+ subject { object.evaluate(instance) }
5
+
6
+ let(:object) { described_class.new(attribute, value) }
7
+ let(:attribute) { Virtus::Attribute::String.new(:title) }
8
+ let(:instance) { Class.new }
9
+
10
+ context 'with a non-callable value' do
11
+ let(:value) { 'something' }
12
+ it { should eql(value) }
13
+ end
14
+
15
+ context 'with a callable value' do
16
+ let(:value) { lambda { |instance, attribute| attribute.name } }
17
+ it { should be(:title) }
18
+ end
19
+ end
@@ -9,7 +9,7 @@ describe Virtus::Attribute::Object, '.descendants' do
9
9
  Virtus::Attribute::Float, Virtus::Attribute::Decimal,
10
10
  Virtus::Attribute::Numeric, Virtus::Attribute::DateTime,
11
11
  Virtus::Attribute::Date, Virtus::Attribute::Boolean,
12
- Virtus::Attribute::Array ]
12
+ Virtus::Attribute::Array, Virtus::Attribute::Class ]
13
13
  end
14
14
 
15
15
  it "should return all known attribute classes" do
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Virtus::Coercion::String, '.to_class' do
4
+ subject { object.to_class(string) }
5
+
6
+ let(:object) { described_class }
7
+
8
+ context "with a String" do
9
+ let(:string) { 'String' }
10
+
11
+ it { should be(String) }
12
+ end
13
+ end
data/virtus.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{virtus}
8
- s.version = "0.0.6"
8
+ s.version = "0.0.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Piotr Solnica}]
12
- s.date = %q{2011-07-30}
12
+ s.date = %q{2011-07-31}
13
13
  s.description = %q{Attributes for your plain ruby objects}
14
14
  s.email = [%q{piotr@rubyverse.com}]
15
15
  s.extra_rdoc_files = [
@@ -39,9 +39,11 @@ Gem::Specification.new do |s|
39
39
  "lib/virtus/attribute.rb",
40
40
  "lib/virtus/attribute/array.rb",
41
41
  "lib/virtus/attribute/boolean.rb",
42
+ "lib/virtus/attribute/class.rb",
42
43
  "lib/virtus/attribute/date.rb",
43
44
  "lib/virtus/attribute/date_time.rb",
44
45
  "lib/virtus/attribute/decimal.rb",
46
+ "lib/virtus/attribute/default_value.rb",
45
47
  "lib/virtus/attribute/float.rb",
46
48
  "lib/virtus/attribute/hash.rb",
47
49
  "lib/virtus/attribute/integer.rb",
@@ -82,14 +84,16 @@ Gem::Specification.new do |s|
82
84
  "spec/unit/shared/attribute/accepted_options.rb",
83
85
  "spec/unit/shared/attribute/get.rb",
84
86
  "spec/unit/shared/attribute/inspect.rb",
85
- "spec/unit/shared/attribute/primitive.rb",
86
87
  "spec/unit/shared/attribute/set.rb",
87
88
  "spec/unit/virtus/attribute/array_spec.rb",
88
89
  "spec/unit/virtus/attribute/boolean_spec.rb",
89
90
  "spec/unit/virtus/attribute/class_methods/determine_type_spec.rb",
91
+ "spec/unit/virtus/attribute/class_spec.rb",
90
92
  "spec/unit/virtus/attribute/date_spec.rb",
91
93
  "spec/unit/virtus/attribute/date_time_spec.rb",
92
94
  "spec/unit/virtus/attribute/decimal_spec.rb",
95
+ "spec/unit/virtus/attribute/default_value/class_methods/new_spec.rb",
96
+ "spec/unit/virtus/attribute/default_value/instance_methods/evaluate_spec.rb",
93
97
  "spec/unit/virtus/attribute/float_spec.rb",
94
98
  "spec/unit/virtus/attribute/hash_spec.rb",
95
99
  "spec/unit/virtus/attribute/integer_spec.rb",
@@ -131,6 +135,7 @@ Gem::Specification.new do |s|
131
135
  "spec/unit/virtus/coercion/integer/class_methods/to_string_spec.rb",
132
136
  "spec/unit/virtus/coercion/object/class_methods/method_missing_spec.rb",
133
137
  "spec/unit/virtus/coercion/string/class_methods/to_boolean_spec.rb",
138
+ "spec/unit/virtus/coercion/string/class_methods/to_class_spec.rb",
134
139
  "spec/unit/virtus/coercion/string/class_methods/to_date_spec.rb",
135
140
  "spec/unit/virtus/coercion/string/class_methods/to_datetime_spec.rb",
136
141
  "spec/unit/virtus/coercion/string/class_methods/to_decimal_spec.rb",
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: virtus
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 6
10
- version: 0.0.6
9
+ - 7
10
+ version: 0.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Piotr Solnica
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-30 00:00:00 Z
18
+ date: 2011-07-31 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: backports
@@ -98,9 +98,11 @@ files:
98
98
  - lib/virtus/attribute.rb
99
99
  - lib/virtus/attribute/array.rb
100
100
  - lib/virtus/attribute/boolean.rb
101
+ - lib/virtus/attribute/class.rb
101
102
  - lib/virtus/attribute/date.rb
102
103
  - lib/virtus/attribute/date_time.rb
103
104
  - lib/virtus/attribute/decimal.rb
105
+ - lib/virtus/attribute/default_value.rb
104
106
  - lib/virtus/attribute/float.rb
105
107
  - lib/virtus/attribute/hash.rb
106
108
  - lib/virtus/attribute/integer.rb
@@ -141,14 +143,16 @@ files:
141
143
  - spec/unit/shared/attribute/accepted_options.rb
142
144
  - spec/unit/shared/attribute/get.rb
143
145
  - spec/unit/shared/attribute/inspect.rb
144
- - spec/unit/shared/attribute/primitive.rb
145
146
  - spec/unit/shared/attribute/set.rb
146
147
  - spec/unit/virtus/attribute/array_spec.rb
147
148
  - spec/unit/virtus/attribute/boolean_spec.rb
148
149
  - spec/unit/virtus/attribute/class_methods/determine_type_spec.rb
150
+ - spec/unit/virtus/attribute/class_spec.rb
149
151
  - spec/unit/virtus/attribute/date_spec.rb
150
152
  - spec/unit/virtus/attribute/date_time_spec.rb
151
153
  - spec/unit/virtus/attribute/decimal_spec.rb
154
+ - spec/unit/virtus/attribute/default_value/class_methods/new_spec.rb
155
+ - spec/unit/virtus/attribute/default_value/instance_methods/evaluate_spec.rb
152
156
  - spec/unit/virtus/attribute/float_spec.rb
153
157
  - spec/unit/virtus/attribute/hash_spec.rb
154
158
  - spec/unit/virtus/attribute/integer_spec.rb
@@ -190,6 +194,7 @@ files:
190
194
  - spec/unit/virtus/coercion/integer/class_methods/to_string_spec.rb
191
195
  - spec/unit/virtus/coercion/object/class_methods/method_missing_spec.rb
192
196
  - spec/unit/virtus/coercion/string/class_methods/to_boolean_spec.rb
197
+ - spec/unit/virtus/coercion/string/class_methods/to_class_spec.rb
193
198
  - spec/unit/virtus/coercion/string/class_methods/to_date_spec.rb
194
199
  - spec/unit/virtus/coercion/string/class_methods/to_datetime_spec.rb
195
200
  - spec/unit/virtus/coercion/string/class_methods/to_decimal_spec.rb
@@ -1,15 +0,0 @@
1
- shared_examples_for 'Attribute.primitive?' do
2
- subject { described_class.primitive?(value) }
3
-
4
- let(:attribute) { described_class.new(attribute_name) }
5
-
6
- context 'with a primitive value' do
7
- let(:value) { attribute_value }
8
- it { should be(true) }
9
- end
10
-
11
- context 'with a non-primitive value' do
12
- let(:value) { nil }
13
- it { should be(false) }
14
- end
15
- end