virtus 0.0.9 → 0.0.10

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.
@@ -0,0 +1,11 @@
1
+ doc
2
+ .yardoc
3
+ *.gem
4
+ .bundle
5
+ Gemfile.lock
6
+ pkg/*
7
+ measurements/
8
+ tmp/
9
+ profiling/
10
+ development
11
+ .rbx/
@@ -13,7 +13,6 @@ env:
13
13
  - JRUBY_OPTS="--1.8"
14
14
  - JRUBY_OPTS="--1.9"
15
15
  - RBXOPT="-X18"
16
- - RBXOPT="-X19"
17
16
  matrix:
18
17
  exclude:
19
18
  # exclude 1.8.7
@@ -1,15 +1,22 @@
1
- # v0.0.8 to-be-released
1
+ # v0.0.10 to-be-released
2
+
3
+ * [fixed] Default values are now duped on evaluate (rclosner)
4
+ * [fixed] Allow to override attribute mutator methods (senny)
5
+
6
+ [Compare v0.0.9..master](https://github.com/solnic/virtus/compare/v0.0.9...master)
7
+
8
+ # v0.0.9 2011-10-11
2
9
 
3
10
  * [fixed] Fix in type lookup for anonymous classes (dkubb)
4
11
 
5
- [Compare v0.0.8..master](https://github.com/solnic/virtus/compare/v0.0.8...master)
12
+ [Compare v0.0.8..v0.0.9](https://github.com/solnic/virtus/compare/v0.0.8...v0.0.9)
6
13
 
7
14
  # v0.0.8 2011-08-25
8
15
 
9
16
  * [fixed] Fixed conflict with ActiveModel (RichGuk)
10
17
  * [changed] Renamed Coercion::String.to_class => Coercion::String.to_constant (emmanuel)
11
18
 
12
- [Compare v0.0.7..master](https://github.com/solnic/virtus/compare/v0.0.7...v0.0.8)
19
+ [Compare v0.0.7..v0.0.8](https://github.com/solnic/virtus/compare/v0.0.7...v0.0.8)
13
20
 
14
21
  # v0.0.7 2011-07-31
15
22
 
data/Gemfile CHANGED
@@ -1,10 +1,6 @@
1
1
  source :rubygems
2
2
 
3
- group :development do
4
- gem 'backports', '~> 2.3.0'
5
- gem 'jeweler', '~> 1.6.4'
6
- gem 'rspec', '~> 2.6.0'
7
- end
3
+ gemspec
8
4
 
9
5
  group :metrics do
10
6
  gem 'flay', '~> 1.4.2'
@@ -12,9 +8,11 @@ group :metrics do
12
8
  gem 'reek', '~> 1.2.8', :git => 'git://github.com/dkubb/reek.git'
13
9
  gem 'roodi', '~> 2.1.0'
14
10
  gem 'yardstick', '~> 0.4.0'
11
+ gem 'fattr'
12
+ gem 'arrayfields'
13
+ gem 'map'
15
14
 
16
15
  platforms :mri_18 do
17
- gem 'heckle', '~> 1.4.3'
18
16
  gem 'json', '~> 1.5.3'
19
17
  gem 'metric_fu', '~> 2.1.1'
20
18
  gem 'mspec', '~> 1.5.17'
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
- # Virtus [![Build Status](http://travis-ci.org/solnic/virtus.png)](http://travis-ci.org/solnic/virtus)
1
+ virtus
2
+ ======
3
+
4
+ [![Build Status](http://travis-ci.org/solnic/virtus.png)](http://travis-ci.org/solnic/virtus)
2
5
 
3
6
  This is a partial extraction of the DataMapper [Property
4
7
  API](http://rubydoc.info/github/datamapper/dm-core/master/DataMapper/Property)
@@ -8,123 +11,159 @@ reinventing the wheel all over again. It is also suitable for any other
8
11
  usecase where you need to extend your ruby objects with attributes that require
9
12
  data type coercions.
10
13
 
11
- ## Installation
14
+ Installation
15
+ ------------
12
16
 
13
- gem i virtus
17
+ ``` terminal
18
+ $ gem install virtus
19
+ ```
14
20
 
15
- ## Basic Usage
21
+ or
16
22
 
17
- require 'virtus'
23
+ ``` ruby
24
+ # ./Gemfile
18
25
 
19
- class User
20
- include Virtus
26
+ gem 'virtus', '0.0.7'
27
+ ```
21
28
 
22
- attribute :name, String
23
- attribute :age, Integer
24
- attribute :birthday, DateTime
25
- end
29
+ Examples
30
+ --------
26
31
 
27
- # setting attributes in the constructor
28
- user = User.new(:name => 'Piotr', :age => 28)
29
32
 
30
- # attribute readers
31
- user.name # => "Piotr"
33
+ ``` ruby
34
+ require 'virtus'
32
35
 
33
- # hash of attributes
34
- user.attributes # => { :name => "Piotr" }
36
+ class User
37
+ include Virtus
35
38
 
36
- # automatic coercion
37
- user.age = '28'
38
- user.age # => 28
39
+ attribute :name, String
40
+ attribute :age, Integer
41
+ attribute :birthday, DateTime
42
+ end
39
43
 
40
- user.birthday = 'November 18th, 1983'
41
- user.birthday # => #<DateTime: 1983-11-18T00:00:00+00:00 (4891313/2,0/1,2299161)>
44
+ user = User.new :name => 'Piotr', :age => 28
45
+ user.attributes
46
+ # => { :name => "Piotr", :age => 28 }
42
47
 
43
- ## Default values
48
+ user.name
49
+ # => "Piotr"
44
50
 
45
- require 'virtus'
51
+ user.age = '28'
52
+ # => 28
53
+ user.age.class
54
+ # => Fixnum
46
55
 
47
- class Page
48
- include Virtus
56
+ user.birthday = 'November 18th, 1983'
57
+ # => #<DateTime: 1983-11-18T00:00:00+00:00 (4891313/2,0/1,2299161)>
58
+ ```
49
59
 
50
- attribute :title, String
51
- attribute :slug, String, :default => lambda { |post, attribute| post.title.downcase.gsub(' ', '-') }
52
- attribute :view_count, Integer, :default => 0
53
- end
54
60
 
55
- page = Page.new(:title => 'Virtus Is Awesome')
56
- page.slug # => 'virtus-is-awesome'
57
- page.view_count # => 0
61
+ **Default values**
58
62
 
59
- ## Coercions
63
+ ``` ruby
64
+ require 'virtus'
60
65
 
61
- Virtus comes with a builtin coercion library. It's super easy to add your own
62
- coercion classes. Take a look:
66
+ class Page
67
+ include Virtus
63
68
 
64
- require 'virtus'
65
- require 'digest/md5'
69
+ attribute :title, String
70
+ attribute :views, Integer, :default => 0
71
+ attribute :slug, String, :default => lambda { |page, attribute| page.title.downcase.gsub(' ', '-') }
72
+ end
66
73
 
67
- class MD5 < Virtus::Attribute::Object
68
- primitive String
69
- coercion_method :to_md5
70
- end
74
+ page = Page.new :title => 'Virtus Is Awesome'
75
+ page.slug
76
+ # => 'virtus-is-awesome'
77
+ page.views
78
+ # => 0
79
+ ```
71
80
 
72
- module Virtus
73
- class Coercion
74
- class String < Virtus::Coercion::Object
75
- def self.to_md5(value)
76
- Digest::MD5.hexdigest(value)
77
- end
78
- end
79
- end
80
- end
81
+ **Adding Coercions**
82
+
83
+ Virtus comes with a builtin coercion library.
84
+ It's super easy to add your own coercion classes.
85
+ Take a look:
86
+
87
+ ``` ruby
88
+ require 'virtus'
89
+ require 'digest/md5'
81
90
 
82
- class User
83
- include Virtus
91
+ # Our new attribute type
92
+ class MD5 < Virtus::Attribute::Object
93
+ primitive String
94
+ coercion_method :to_md5
95
+ end
84
96
 
85
- attribute :name, String
86
- attribute :password, MD5
97
+ # Defining the Coercion method
98
+ module Virtus
99
+ class Coercion
100
+ class String < Virtus::Coercion::Object
101
+ def self.to_md5(value)
102
+ Digest::MD5.hexdigest value
103
+ end
87
104
  end
105
+ end
106
+ end
88
107
 
89
- user = User.new(:name => 'Piotr', :password => 'foobar')
90
- user.name # => 'Piotr'
91
- user.password # => '3858f62230ac3c915f300c664312c63f'
108
+ # And now the user!
109
+ class User
110
+ include Virtus
92
111
 
93
- ## Custom Attributes
112
+ attribute :name, String
113
+ attribute :password, MD5
114
+ end
94
115
 
95
- require 'virtus'
96
- require 'json'
116
+ user = User.new :name => 'Piotr', :password => 'foobar'
117
+ user.name
118
+ # => 'Piotr'
119
+ user.password
120
+ # => '3858f62230ac3c915f300c664312c63f'
121
+ ```
97
122
 
98
- module MyApp
99
- module Attributes
100
- class JSON < Virtus::Attribute::Object
101
- primitive Hash
123
+ **Custom Attributes**
102
124
 
103
- def coerce(value)
104
- ::JSON.parse(value)
105
- end
106
- end
107
- end
125
+ ``` ruby
126
+ require 'virtus'
127
+ require 'json'
108
128
 
109
- class User
110
- include Virtus
129
+ module MyAppClass
111
130
 
112
- attribute :info, Attributes::JSON
131
+ # Defining the custom attribute(s)
132
+ module Attributes
133
+ class JSON < Virtus::Attribute::Object
134
+ primitive Hash
135
+
136
+ def coerce(value)
137
+ ::JSON.parse value
113
138
  end
114
139
  end
140
+ end
141
+
142
+ class User
143
+ include Virtus
115
144
 
116
- user = MyApp::User.new
145
+ attribute :info, Attributes::JSON
146
+ end
147
+ end
117
148
 
118
- user.info = '{"email":"john@domain.com"}'
119
- user.info # => {"email"=>"john@domain.com"}
149
+ user = MyApp::User.new
150
+ user.info = '{"email":"john@domain.com"}'
151
+ # => {"email"=>"john@domain.com"}
152
+ user.info.class
153
+ # => Hash
154
+ ```
120
155
 
121
- ## Contributors
156
+
157
+ Credits
158
+ -------
122
159
 
123
160
  * Dan Kubb ([dkubb](https://github.com/dkubb))
124
161
  * Chris Corbyn ([d11wtq](https://github.com/d11wtq))
125
162
  * Emmanuel Gomez ([emmanuel](https://github.com/emmanuel))
126
163
 
127
- ## Note on Patches/Pull Requests
164
+
165
+ Contributing
166
+ -------------
128
167
 
129
168
  * Fork the project.
130
169
  * Make your feature addition or bug fix.
@@ -134,6 +173,26 @@ coercion classes. Take a look:
134
173
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
135
174
  * Send me a pull request. Bonus points for topic branches.
136
175
 
137
- ## Copyright
138
-
139
- Copyright (c) 2011 Piotr Solnica. See LICENSE for details.
176
+ License
177
+ -------
178
+
179
+ Copyright (c) 2011 Piotr Solnica
180
+
181
+ Permission is hereby granted, free of charge, to any person obtaining
182
+ a copy of this software and associated documentation files (the
183
+ "Software"), to deal in the Software without restriction, including
184
+ without limitation the rights to use, copy, modify, merge, publish,
185
+ distribute, sublicense, and/or sell copies of the Software, and to
186
+ permit persons to whom the Software is furnished to do so, subject to
187
+ the following conditions:
188
+
189
+ The above copyright notice and this permission notice shall be
190
+ included in all copies or substantial portions of the Software.
191
+
192
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
193
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
194
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
195
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
196
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
197
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
198
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,21 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
- require 'jeweler'
4
- require 'rspec/core/rake_task'
5
-
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = 'virtus'
8
- gem.platform = Gem::Platform::RUBY
9
- gem.authors = [ 'Piotr Solnica' ]
10
- gem.email = [ 'piotr@rubyverse.com' ]
11
- gem.homepage = 'https://github.com/solnic/virtus'
12
- gem.summary = 'Attributes for your plain ruby objects'
13
- gem.description = gem.summary
14
- end
15
-
16
- Jeweler::GemcutterTasks.new
17
3
 
18
4
  FileList['tasks/**/*.rake'].each { |task| import task }
19
5
 
20
- desc 'Default: run specs.'
6
+ desc 'Default: run all specs'
21
7
  task :default => :spec
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 20
3
- total_score: 261
3
+ total_score: 257
@@ -5,7 +5,7 @@ CaseMissingElseCheck: { }
5
5
  ClassLineCountCheck: { line_count: 309 }
6
6
  ClassNameCheck: { pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ }
7
7
  ClassVariableCheck: { }
8
- CyclomaticComplexityBlockCheck: { complexity: 2 }
8
+ CyclomaticComplexityBlockCheck: { complexity: 4 }
9
9
  CyclomaticComplexityMethodCheck: { complexity: 4 }
10
10
  EmptyRescueBodyCheck: { }
11
11
  ForLoopCheck: { }
@@ -26,7 +26,11 @@ LongParameterList:
26
26
  enabled: true
27
27
  overrides: {}
28
28
  FeatureEnvy:
29
- exclude: [Virtus::Coercion::TimeCoercions#to_string, Virtus::Coercion::TimeCoercions#coerce_with_method]
29
+ exclude: [
30
+ Virtus::Coercion::TimeCoercions#to_string,
31
+ Virtus::Coercion::TimeCoercions#coerce_with_method,
32
+ Virtus::TypeLookup#determine_type_from_primitive
33
+ ]
30
34
  enabled: true
31
35
  ClassVariable:
32
36
  exclude: []
@@ -55,7 +59,9 @@ LongMethod:
55
59
  enabled: true
56
60
  Duplication:
57
61
  allow_calls: []
58
- exclude: []
62
+ exclude: [
63
+ Virtus::Attribute::DefaultValue#evaluate
64
+ ]
59
65
  enabled: true
60
66
  max_calls: 1
61
67
  UtilityFunction:
@@ -1,6 +1,6 @@
1
1
  require './spec/spec_helper'
2
2
 
3
- class MD5 < Virtus::Attribute::Object
3
+ class Md5 < Virtus::Attribute::Object
4
4
  primitive String
5
5
  coercion_method :to_md5
6
6
  end
@@ -19,7 +19,7 @@ class User
19
19
  include Virtus
20
20
 
21
21
  attribute :name, String
22
- attribute :password, MD5
22
+ attribute :password, Md5
23
23
  end
24
24
 
25
25
  describe User do
@@ -0,0 +1,40 @@
1
+ require './spec/spec_helper'
2
+
3
+ class Article
4
+ include Virtus
5
+
6
+ attribute :author, String
7
+
8
+ def author
9
+ super || '<unknown>'
10
+ end
11
+
12
+ def author=(name)
13
+ super unless name == 'Brad'
14
+ end
15
+
16
+ end
17
+
18
+ describe Article, 'override' do
19
+
20
+ it 'Alice is an allowed author' do
21
+ Article.new(:author => 'Alice').author.should == 'Alice'
22
+ end
23
+
24
+ it 'Brad isn not an allowed author' do
25
+ Article.new(:author => 'Brad').author.should == '<unknown>'
26
+ end
27
+
28
+ context 'with author' do
29
+ subject { Article.new(:author => 'John') }
30
+
31
+ its(:author) { should == 'John' }
32
+ end
33
+
34
+ context 'without author' do
35
+ subject { Article.new }
36
+
37
+ its(:author) { should == '<unknown>' }
38
+ end
39
+
40
+ end