virtus 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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