virtus 0.0.2 → 0.0.3
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/.gitignore +3 -0
- data/.rvmrc +1 -1
- data/Gemfile +20 -1
- data/History.txt +21 -0
- data/README.markdown +2 -2
- data/Rakefile +1 -2
- data/VERSION +1 -1
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +18 -0
- data/config/site.reek +91 -0
- data/config/yardstick.yml +2 -0
- data/lib/virtus.rb +51 -45
- data/lib/virtus/attribute.rb +301 -0
- data/lib/virtus/attribute/array.rb +17 -0
- data/lib/virtus/attribute/boolean.rb +60 -0
- data/lib/virtus/attribute/date.rb +35 -0
- data/lib/virtus/attribute/date_time.rb +34 -0
- data/lib/virtus/attribute/decimal.rb +24 -0
- data/lib/virtus/attribute/float.rb +33 -0
- data/lib/virtus/attribute/hash.rb +18 -0
- data/lib/virtus/attribute/integer.rb +30 -0
- data/lib/virtus/{attributes → attribute}/numeric.rb +2 -3
- data/lib/virtus/{attributes → attribute}/object.rb +2 -1
- data/lib/virtus/attribute/string.rb +31 -0
- data/lib/virtus/attribute/time.rb +34 -0
- data/lib/virtus/class_methods.rb +25 -8
- data/lib/virtus/instance_methods.rb +48 -9
- data/lib/virtus/support/chainable.rb +4 -6
- data/lib/virtus/typecast/boolean.rb +27 -0
- data/lib/virtus/typecast/numeric.rb +82 -0
- data/lib/virtus/typecast/time.rb +162 -0
- data/spec/integration/virtus/attributes/attribute/typecast_spec.rb +4 -4
- data/spec/integration/virtus/class_methods/attribute_spec.rb +1 -1
- data/spec/integration/virtus/class_methods/attributes_spec.rb +3 -2
- data/spec/integration/virtus/class_methods/const_missing_spec.rb +2 -2
- data/spec/rcov.opts +6 -0
- data/spec/spec_helper.rb +0 -9
- data/spec/unit/shared/attribute.rb +8 -8
- data/spec/unit/virtus/{attributes → attribute}/array_spec.rb +1 -1
- data/spec/unit/virtus/attribute/attribute_spec.rb +12 -0
- data/spec/unit/virtus/{attributes → attribute}/boolean_spec.rb +4 -4
- data/spec/unit/virtus/{attributes → attribute}/date_spec.rb +13 -7
- data/spec/unit/virtus/{attributes → attribute}/date_time_spec.rb +31 -10
- data/spec/unit/virtus/{attributes → attribute}/decimal_spec.rb +18 -18
- data/spec/unit/virtus/{attributes → attribute}/float_spec.rb +18 -18
- data/spec/unit/virtus/{attributes → attribute}/hash_spec.rb +1 -1
- data/spec/unit/virtus/{attributes → attribute}/integer_spec.rb +18 -18
- data/spec/unit/virtus/attribute/numeric/class_methods/descendants_spec.rb +15 -0
- data/spec/unit/virtus/attribute/object/class_methods/descendants_spec.rb +16 -0
- data/spec/unit/virtus/{attributes → attribute}/string_spec.rb +2 -2
- data/spec/unit/virtus/{attributes → attribute}/time_spec.rb +19 -9
- data/spec/unit/virtus/class_methods/new_spec.rb +7 -7
- data/spec/unit/virtus/determine_type_spec.rb +4 -4
- data/spec/unit/virtus/instance_methods/attribute_get_spec.rb +1 -1
- data/spec/unit/virtus/instance_methods/attribute_set_spec.rb +2 -2
- data/spec/unit/virtus/instance_methods/attributes_spec.rb +2 -2
- data/tasks/metrics/ci.rake +7 -0
- data/tasks/metrics/flay.rake +41 -0
- data/tasks/metrics/flog.rake +43 -0
- data/tasks/metrics/heckle.rake +261 -0
- data/tasks/metrics/metric_fu.rake +29 -0
- data/tasks/metrics/reek.rake +9 -0
- data/tasks/metrics/roodi.rake +15 -0
- data/tasks/metrics/yardstick.rake +23 -0
- data/tasks/spec.rake +26 -0
- data/tasks/yard.rake +9 -0
- data/virtus.gemspec +48 -33
- metadata +51 -41
- data/lib/virtus/attributes/array.rb +0 -8
- data/lib/virtus/attributes/attribute.rb +0 -214
- data/lib/virtus/attributes/boolean.rb +0 -39
- data/lib/virtus/attributes/date.rb +0 -44
- data/lib/virtus/attributes/date_time.rb +0 -43
- data/lib/virtus/attributes/decimal.rb +0 -24
- data/lib/virtus/attributes/float.rb +0 -20
- data/lib/virtus/attributes/hash.rb +0 -8
- data/lib/virtus/attributes/integer.rb +0 -20
- data/lib/virtus/attributes/string.rb +0 -11
- data/lib/virtus/attributes/time.rb +0 -45
- data/lib/virtus/attributes/typecast/numeric.rb +0 -32
- data/lib/virtus/attributes/typecast/time.rb +0 -27
- data/spec/unit/virtus/attributes/attribute_spec.rb +0 -13
- data/spec/unit/virtus/attributes/numeric/class_methods/descendants_spec.rb +0 -15
- data/spec/unit/virtus/attributes/object/class_methods/descendants_spec.rb +0 -16
@@ -0,0 +1,17 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class Post
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :tags, Array
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# post = Post.new(:tags => %w(red green blue))
|
12
|
+
class Array < Object
|
13
|
+
primitive ::Array
|
14
|
+
complex true
|
15
|
+
end # Integer
|
16
|
+
end # Attributes
|
17
|
+
end # Virtus
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Bolean attribute allows true or false values to be set
|
4
|
+
# Additionally it adds boolean reader method, like "admin?"
|
5
|
+
#
|
6
|
+
# Example usage:
|
7
|
+
#
|
8
|
+
# class Post
|
9
|
+
# include Virtus
|
10
|
+
#
|
11
|
+
# attribute :published, Boolean
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# post = Post.new(:published => false)
|
15
|
+
# post.published? # => false
|
16
|
+
#
|
17
|
+
class Boolean < Object
|
18
|
+
primitive TrueClass
|
19
|
+
|
20
|
+
# Returns if the given value is either true or false
|
21
|
+
#
|
22
|
+
# @return [TrueClass,FalseClass]
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
def primitive?(value)
|
26
|
+
value.equal?(true) || value.equal?(false)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Coerce value into true or false
|
30
|
+
#
|
31
|
+
# @see Virtus::Typecast::Boolean.call
|
32
|
+
#
|
33
|
+
# @return [TrueClass,FalseClass]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
def typecast_to_primitive(value)
|
37
|
+
Typecast::Boolean.call(value)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Creates standard and boolean attribute reader methods
|
41
|
+
#
|
42
|
+
# @return [NilClass]
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
def add_reader_method(model)
|
46
|
+
super
|
47
|
+
|
48
|
+
model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
49
|
+
chainable(:attribute) do
|
50
|
+
#{reader_visibility}
|
51
|
+
|
52
|
+
def #{name}?
|
53
|
+
#{name}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
RUBY
|
57
|
+
end
|
58
|
+
end # Boolean
|
59
|
+
end # Attributes
|
60
|
+
end # Virtus
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class Post
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :published_on, Date
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Post.new(:published_on => Date.today)
|
12
|
+
#
|
13
|
+
# # typecasting from a string
|
14
|
+
# Post.new(:published_on => '2011/06/09')
|
15
|
+
#
|
16
|
+
# # typecasting from a hash
|
17
|
+
# Post.new(:published_on => { :year => 2011, :month => 6, :day => 9 })
|
18
|
+
#
|
19
|
+
# # typecasting from an object which implements #to_date
|
20
|
+
# Post.new(:published_on => DateTime.now)
|
21
|
+
#
|
22
|
+
class Date < Object
|
23
|
+
primitive ::Date
|
24
|
+
|
25
|
+
# @see Virtus::Typecast::Time.to_date
|
26
|
+
#
|
27
|
+
# @return [Date]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
def typecast_to_primitive(value)
|
31
|
+
Typecast::Time.to_date(value)
|
32
|
+
end
|
33
|
+
end # Date
|
34
|
+
end # Attributes
|
35
|
+
end # Virtus
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class Post
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :published_at, DateTime
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Post.new(:published_at => DateTime.now)
|
12
|
+
#
|
13
|
+
# # typecasting from a string
|
14
|
+
# Post.new(:published_on => '2011/06/09 10:48')
|
15
|
+
#
|
16
|
+
# # typecasting from a hash
|
17
|
+
# Post.new(:published_on => {
|
18
|
+
# :year => 2011, :month => 6, :day => 9, :hour => 10, :minutes => 48 })
|
19
|
+
#
|
20
|
+
# # typecasting from an object which implements #to_datetime
|
21
|
+
# Post.new(:published_on => Time.now)
|
22
|
+
#
|
23
|
+
class DateTime < Object
|
24
|
+
primitive ::DateTime
|
25
|
+
|
26
|
+
# @see Virtus::Typecast::Time.to_datetime
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
def typecast_to_primitive(value)
|
30
|
+
Typecast::Time.to_datetime(value)
|
31
|
+
end
|
32
|
+
end # DateTime
|
33
|
+
end # Attributes
|
34
|
+
end # Virtus
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class ExchangeRate
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :dollar, Decimal
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# ExchangeRate.new(:dollar => '2.6948')
|
12
|
+
#
|
13
|
+
class Decimal < Numeric
|
14
|
+
primitive ::BigDecimal
|
15
|
+
|
16
|
+
# @see Virtus::Typecast::Numeric.to_d
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
def typecast_to_primitive(value)
|
20
|
+
Typecast::Numeric.to_d(value)
|
21
|
+
end
|
22
|
+
end # Decimal
|
23
|
+
end # Attributes
|
24
|
+
end # Virtus
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class ExchangeRate
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :dollar, Float
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# ExchangeRate.new(:dollar => 2.69)
|
12
|
+
#
|
13
|
+
# # typecasting from a string
|
14
|
+
# ExchangeRate.new(:dollar => '2.69')
|
15
|
+
#
|
16
|
+
# # typecasting from an integer
|
17
|
+
# ExchangeRate.new(:dollar => 2)
|
18
|
+
#
|
19
|
+
# # typecasting from an object which implements #to_f
|
20
|
+
# ExchangeRate.new(:dollar => BigDecimal.new('2.69')
|
21
|
+
#
|
22
|
+
class Float < Numeric
|
23
|
+
primitive ::Float
|
24
|
+
|
25
|
+
# @see Virtus::Typecast::Numeric.to_f
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
def typecast_to_primitive(value)
|
29
|
+
Typecast::Numeric.to_f(value)
|
30
|
+
end
|
31
|
+
end # Float
|
32
|
+
end # Attributes
|
33
|
+
end # Virtus
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class Post
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :meta, Hash
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Post.new(:meta => { :tags => %w(foo bar) })
|
12
|
+
#
|
13
|
+
class Hash < Object
|
14
|
+
primitive ::Hash
|
15
|
+
complex true
|
16
|
+
end # Integer
|
17
|
+
end # Attributes
|
18
|
+
end # Virtus
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class Post
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :read_count, Integer
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Post.new(:read_count => 100)
|
12
|
+
#
|
13
|
+
# # typecasting from a string
|
14
|
+
# Post.new(:read_count => '100')
|
15
|
+
#
|
16
|
+
# # typecasting from an object that implements #to_i
|
17
|
+
# Post.new(:read_count => 100.0)
|
18
|
+
#
|
19
|
+
class Integer < Numeric
|
20
|
+
primitive ::Integer
|
21
|
+
|
22
|
+
# @see Virtus::Typecast::Numeric.to_i
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
def typecast_to_primitive(value)
|
26
|
+
Typecast::Numeric.to_i(value)
|
27
|
+
end
|
28
|
+
end # Integer
|
29
|
+
end # Attributes
|
30
|
+
end # Virtus
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage
|
4
|
+
#
|
5
|
+
# class User
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :name, String
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# User.new(:name => 'John')
|
12
|
+
#
|
13
|
+
# # typecasting from an object which implements #to_s
|
14
|
+
# User.new(:name => :John)
|
15
|
+
#
|
16
|
+
class String < Object
|
17
|
+
primitive ::String
|
18
|
+
|
19
|
+
# Typecast the given value to a string
|
20
|
+
#
|
21
|
+
# @param [Object]
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
def typecast_to_primitive(value)
|
27
|
+
value.to_s
|
28
|
+
end
|
29
|
+
end # String
|
30
|
+
end # Attributes
|
31
|
+
end # Virtus
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Virtus
|
2
|
+
class Attribute
|
3
|
+
# Example usage:
|
4
|
+
#
|
5
|
+
# class Post
|
6
|
+
# include Virtus
|
7
|
+
#
|
8
|
+
# attribute :published_at, Time
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Post.new(:published_at => Time.now)
|
12
|
+
#
|
13
|
+
# # typecasting from a string
|
14
|
+
# Post.new(:published_at => '2011/06/09 11:08')
|
15
|
+
#
|
16
|
+
# # typecasting from a hash
|
17
|
+
# Post.new(:published_at => {
|
18
|
+
# :year => 2011, :month => 6, :day => 9, :hour => 11, :minutes => 8 })
|
19
|
+
#
|
20
|
+
# # typecasting from an object which implements #to_time
|
21
|
+
# Post.new(:published_at => DateTime.now)
|
22
|
+
#
|
23
|
+
class Time < Object
|
24
|
+
primitive ::Time
|
25
|
+
|
26
|
+
# @see Virtus::Typecast::Time.to_time
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
def typecast_to_primitive(value)
|
30
|
+
Typecast::Time.to_time(value)
|
31
|
+
end
|
32
|
+
end # Time
|
33
|
+
end # Attributes
|
34
|
+
end # Virtus
|
data/lib/virtus/class_methods.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Virtus
|
2
|
+
# Class methods that are added when you include Virtus
|
2
3
|
module ClassMethods
|
3
|
-
# Defines an attribute on an object's class
|
4
|
-
#
|
5
|
-
# Usage:
|
4
|
+
# Defines an attribute on an object's class
|
6
5
|
#
|
6
|
+
# @example
|
7
7
|
# class Book
|
8
8
|
# include Virtus
|
9
9
|
#
|
@@ -26,11 +26,28 @@ module Virtus
|
|
26
26
|
#
|
27
27
|
# @api public
|
28
28
|
def attribute(name, type, options = {})
|
29
|
-
attribute_klass
|
30
|
-
|
29
|
+
attribute_klass = Virtus.determine_type(type)
|
30
|
+
attribute = attribute_klass.new(name, options)
|
31
|
+
|
32
|
+
attribute.add_reader_method(self)
|
33
|
+
attribute.add_writer_method(self)
|
34
|
+
|
35
|
+
attributes[name] = attribute
|
31
36
|
end
|
32
37
|
|
33
|
-
# Returns all the attributes defined on a Class
|
38
|
+
# Returns all the attributes defined on a Class
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# class User
|
42
|
+
# include Virtus
|
43
|
+
#
|
44
|
+
# attribute :name, String
|
45
|
+
# attribute :age, Integer
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# User.attributes # =>
|
49
|
+
#
|
50
|
+
# TODO: implement inspect so the output is not cluttered - solnic
|
34
51
|
#
|
35
52
|
# @return [Hash]
|
36
53
|
# an attributes hash indexed by attribute names
|
@@ -42,11 +59,11 @@ module Virtus
|
|
42
59
|
|
43
60
|
private
|
44
61
|
|
45
|
-
# Hooks into const missing process to determine types of attributes
|
62
|
+
# Hooks into const missing process to determine types of attributes
|
46
63
|
#
|
47
64
|
# It is used when an attribute is defined and a global class like String
|
48
65
|
# or Integer is provided as the type which needs to be mapped to
|
49
|
-
# Virtus::Attributes::String and Virtus::Attributes::Integer
|
66
|
+
# Virtus::Attributes::String and Virtus::Attributes::Integer
|
50
67
|
#
|
51
68
|
# @param [String] name
|
52
69
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Virtus
|
2
|
+
# Instance methods that are added when you include Virtus
|
2
3
|
module InstanceMethods
|
3
|
-
#
|
4
|
-
# an object.
|
4
|
+
# Set attributes during initialization of an object
|
5
5
|
#
|
6
6
|
# @param [Hash] attributes
|
7
7
|
# the attributes hash to be set
|
@@ -15,6 +15,16 @@ module Virtus
|
|
15
15
|
|
16
16
|
# Returns a value of the attribute with the given name
|
17
17
|
#
|
18
|
+
# @example
|
19
|
+
# class User
|
20
|
+
# include Virtus
|
21
|
+
#
|
22
|
+
# attribute :name, String
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# user = User.new(:name => 'John')
|
26
|
+
# user.attribute_get(:name) # => "john"
|
27
|
+
#
|
18
28
|
# @param [Symbol] name
|
19
29
|
# a name of an attribute
|
20
30
|
#
|
@@ -28,6 +38,17 @@ module Virtus
|
|
28
38
|
|
29
39
|
# Sets a value of the attribute with the given name
|
30
40
|
#
|
41
|
+
# @example
|
42
|
+
# class User
|
43
|
+
# include Virtus
|
44
|
+
#
|
45
|
+
# attribute :name, String
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# user = User.new
|
49
|
+
# user.attribute_set(:name) # => "john"
|
50
|
+
# user.name # => "john"
|
51
|
+
#
|
31
52
|
# @param [Symbol] name
|
32
53
|
# a name of an attribute
|
33
54
|
#
|
@@ -44,6 +65,17 @@ module Virtus
|
|
44
65
|
|
45
66
|
# Mass-assign of attribute values
|
46
67
|
#
|
68
|
+
# @example
|
69
|
+
# class User
|
70
|
+
# include Virtus
|
71
|
+
#
|
72
|
+
# attribute :name, String
|
73
|
+
# attribute :age, Integer
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# user = User.new
|
77
|
+
# user.attributes = { :name => 'John', :age => 28 }
|
78
|
+
#
|
47
79
|
# @param [Hash] attributes
|
48
80
|
# a hash of attribute values to be set on an object
|
49
81
|
#
|
@@ -53,14 +85,23 @@ module Virtus
|
|
53
85
|
# @api public
|
54
86
|
def attributes=(attributes)
|
55
87
|
attributes.each do |name, value|
|
56
|
-
if
|
57
|
-
__send__(writer_name, value)
|
58
|
-
end
|
88
|
+
attribute_set(name, value) if respond_to?("#{name}=")
|
59
89
|
end
|
60
90
|
end
|
61
91
|
|
62
92
|
# Returns a hash of all publicly accessible attributes
|
63
93
|
#
|
94
|
+
# @example
|
95
|
+
# class User
|
96
|
+
# include Virtus
|
97
|
+
#
|
98
|
+
# attribute :name, String
|
99
|
+
# attribute :age, Integer
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# user = User.new(:name => 'John', :age => 28)
|
103
|
+
# user.attributes # => { :name => 'John', :age => 28 }
|
104
|
+
#
|
64
105
|
# @return [Hash]
|
65
106
|
# the attributes
|
66
107
|
#
|
@@ -68,10 +109,8 @@ module Virtus
|
|
68
109
|
def attributes
|
69
110
|
attributes = {}
|
70
111
|
|
71
|
-
self.class.attributes.
|
72
|
-
if
|
73
|
-
attributes[name] = __send__(attribute.name)
|
74
|
-
end
|
112
|
+
self.class.attributes.each_key do |name|
|
113
|
+
attributes[name] = attribute_get(name) if respond_to?(name)
|
75
114
|
end
|
76
115
|
|
77
116
|
attributes
|