virtus 0.0.6 → 0.0.7

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/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