Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 354 lines (258 sloc) 8.364 kb
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
1 virtus
2 ======
3
6a52b59 Steve Richert Fix build status and add dependency status image to README
laserlemon authored
4 [![Build Status](https://secure.travis-ci.org/solnic/virtus.png)](http://travis-ci.org/solnic/virtus)
5 [![Dependency Status](https://gemnasium.com/solnic/virtus.png)](https://gemnasium.com/solnic/virtus)
f3af067 Piotr Solnica Add codeclimate badge
solnic authored
6 [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/solnic/virtus)
8605e14 Piotr Solnica Update README.md
solnic authored
7
ceed87f Piotr Solnica README update
solnic authored
8 This is a partial extraction of the DataMapper [Property
9 API](http://rubydoc.info/github/datamapper/dm-core/master/DataMapper/Property)
226f299 Piotr Solnica README update
solnic authored
10 with various modifications and improvements. The goal is to provide a common API
11 for defining attributes on a model so all ORMs/ODMs could use it instead of
12 reinventing the wheel all over again. It is also suitable for any other
13 usecase where you need to extend your ruby objects with attributes that require
105d4b6 Piotr Solnica Add information about coercions to README file
solnic authored
14 data type coercions.
ceed87f Piotr Solnica README update
solnic authored
15
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
16 Installation
17 ------------
ceed87f Piotr Solnica README update
solnic authored
18
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
19 ``` terminal
20 $ gem install virtus
21 ```
ceed87f Piotr Solnica README update
solnic authored
22
5273374 Yves Senn pretty installation notes
senny authored
23 or in your **Gemfile**
ceed87f Piotr Solnica README update
solnic authored
24
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
25 ``` ruby
ba8a6f4 Piotr Solnica Add information about EV to the README
solnic authored
26 gem 'virtus'
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
27 ```
ceed87f Piotr Solnica README update
solnic authored
28
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
29 Examples
30 --------
ceed87f Piotr Solnica README update
solnic authored
31
be9930d Dan Kubb Add heading for class usage
dkubb authored
32 ### Using Virtus with Classes
33
34 You can create classes extended with virtus and define attributes:
ceed87f Piotr Solnica README update
solnic authored
35
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
36 ``` ruby
37 class User
38 include Virtus
ceed87f Piotr Solnica README update
solnic authored
39
900f903 Kristian Mandrup works on ruby 1.9.2
authored
40 attributes :first_name, :last_name, String
41 attributes :allow_pets, :allow_smoking, :allow_drinking, Boolean, :as => :rule_options
42
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
43 attribute :age, Integer
44 attribute :birthday, DateTime
45 end
ceed87f Piotr Solnica README update
solnic authored
46
900f903 Kristian Mandrup works on ruby 1.9.2
authored
47 user = User.new(:first_name => 'Piotr', :age => 28)
48 user.attribute_set # => { :first_name => "Piotr", :age => 28 }
9bfc2c6 Piotr Solnica README update
solnic authored
49
900f903 Kristian Mandrup works on ruby 1.9.2
authored
50 user.first_name # => "Piotr"
749e93e Piotr Solnica Add info about default values to README
solnic authored
51
710f757 Yves Senn inline xmp-comments and use consistent spacing
senny authored
52 user.age = '28' # => 28
53 user.age.class # => Fixnum
749e93e Piotr Solnica Add info about default values to README
solnic authored
54
710f757 Yves Senn inline xmp-comments and use consistent spacing
senny authored
55 user.birthday = 'November 18th, 1983' # => #<DateTime: 1983-11-18T00:00:00+00:00 (4891313/2,0/1,2299161)>
900f903 Kristian Mandrup works on ruby 1.9.2
authored
56
57 User.rule_options # => [:allow_pets, :allow_smoking, :allow_drinking]
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
58 ```
749e93e Piotr Solnica Add info about default values to README
solnic authored
59
be9930d Dan Kubb Add heading for class usage
dkubb authored
60 ### Using Virtus with Modules
96bffb4 Piotr Solnica Update README with modules and instances examples
solnic authored
61
62 You can create modules extended with virtus and define attributes for later
63 inclusion in your classes:
64
65 ```ruby
66 module Name
67 include Virtus
68
9ca622f Kristian Mandrup added option to define multiple attributes using deprecated #attributes ...
authored
69 attributes :first_name, :last_name, String
96bffb4 Piotr Solnica Update README with modules and instances examples
solnic authored
70 end
71
72 module Age
73 include Virtus
74
75 attribute :age, Integer
76 end
77
78 class User
79 include Name, Age
80 end
81
9ca622f Kristian Mandrup added option to define multiple attributes using deprecated #attributes ...
authored
82 user = User.new(:first_name => 'John', :last_name => 'Adams', :age => '30')
96bffb4 Piotr Solnica Update README with modules and instances examples
solnic authored
83 ```
84
28a01ee Piotr Solnica Fix headers in README
solnic authored
85 ### Dynamically Extending Instances
96bffb4 Piotr Solnica Update README with modules and instances examples
solnic authored
86
87 It's also possible to dynamically extend an object with Virtus:
88
89 ```ruby
90 class User
91 # nothing here
92 end
93
94 user = User.new
95 user.extend(Virtus)
96 user.attribute :name, String
97 user.name = 'John'
98 user.name # => 'John'
99 ```
749e93e Piotr Solnica Add info about default values to README
solnic authored
100
28a01ee Piotr Solnica Fix headers in README
solnic authored
101 ### Default Values
749e93e Piotr Solnica Add info about default values to README
solnic authored
102
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
103 ``` ruby
104 class Page
105 include Virtus
9bfc2c6 Piotr Solnica README update
solnic authored
106
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
107 attribute :title, String
28a9840 Piotr Solnica Fix whitespace
solnic authored
108
994e344 Piotr Solnica Update README.md
solnic authored
109 # default from a singleton value (integer in this case)
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
110 attribute :views, Integer, :default => 0
51e420b Fabio Rehm Fix default values example
fgrehm authored
111
112 # default from a singleton value (boolean in this case)
113 attribute :published, Boolean, :default => false
114
994e344 Piotr Solnica Update README.md
solnic authored
115 # default from a callable object (proc in this case)
4bb86d8 Yves Senn fix a typo in the README to showoff the default values
senny authored
116 attribute :slug, String, :default => lambda { |page, attribute| page.title.downcase.gsub(' ', '-') }
51e420b Fabio Rehm Fix default values example
fgrehm authored
117
994e344 Piotr Solnica Update README.md
solnic authored
118 # default from a method name as symbol
119 attribute :editor_title, String, :default => :default_editor_title
120
121 def default_editor_title
122 published? ? title : "UNPUBLISHED: #{title}"
123 end
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
124 end
9bfc2c6 Piotr Solnica README update
solnic authored
125
51e420b Fabio Rehm Fix default values example
fgrehm authored
126 page = Page.new(:title => 'Virtus README')
127 page.slug # => 'virtus-readme'
128 page.views # => 0
129 page.published # => false
130 page.editor_title # => "UNPUBLISHED: Virtus README"
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
131 ```
9bfc2c6 Piotr Solnica README update
solnic authored
132
28a01ee Piotr Solnica Fix headers in README
solnic authored
133 ### Embedded Value
ba8a6f4 Piotr Solnica Add information about EV to the README
solnic authored
134
135 ``` ruby
136 class City
137 include Virtus
138
139 attribute :name, String
140 end
141
142 class Address
143 include Virtus
144
9ca622f Kristian Mandrup added option to define multiple attributes using deprecated #attributes ...
authored
145 attributes :street, :zipcode, String
146 attribute :city, City
ba8a6f4 Piotr Solnica Add information about EV to the README
solnic authored
147 end
148
149 class User
150 include Virtus
151
152 attribute :name, String
153 attribute :address, Address
154 end
155
156 user = User.new(:address => {
157 :street => 'Street 1/2', :zipcode => '12345', :city => { :name => 'NYC' } })
158
159 user.address.street # => "Street 1/2"
160 user.address.city.name # => "NYC"
161 ```
162
28a01ee Piotr Solnica Fix headers in README
solnic authored
163 ### Collection Member Coercions
e0147b8 Piotr Solnica Add examples of collection member coercions to the README
solnic authored
164
165 ``` ruby
166 # Support "primitive" classes
167 class Book
168 include Virtus
169
170 attribute :page_numbers, Array[Integer]
171 end
172
173 book = Book.new(:page_numbers => %w[1 2 3])
174 book.page_numbers # => [1, 2, 3]
175
176 # Support EmbeddedValues, too!
177 class Address
178 include Virtus
179
9ca622f Kristian Mandrup added option to define multiple attributes using deprecated #attributes ...
authored
180 attributes :address, :locality, :region, :postal_code, String
e0147b8 Piotr Solnica Add examples of collection member coercions to the README
solnic authored
181 end
182
183 class PhoneNumber
184 include Virtus
185
186 attribute :number, String
187 end
188
189 class User
190 include Virtus
191
192 attribute :phone_numbers, Array[PhoneNumber]
193 attribute :addresses, Set[Address]
194 end
195
196 user = User.new(
197 :phone_numbers => [
198 { :number => '212-555-1212' },
199 { :number => '919-444-3265' } ],
200 :addresses => [
201 { :address => '1234 Any St.', :locality => 'Anytown', :region => "DC", :postal_code => "21234" } ])
202
203 user.phone_numbers # => [#<PhoneNumber:0x007fdb2d3bef88 @number="212-555-1212">, #<PhoneNumber:0x007fdb2d3beb00 @number="919-444-3265">]
204
205 user.addresses # => #<Set: {#<Address:0x007fdb2d3be448 @address="1234 Any St.", @locality="Anytown", @region="DC", @postal_code="21234">}>
206 ```
207
28a01ee Piotr Solnica Fix headers in README
solnic authored
208 ### Value Objects
6d1a987 Piotr Solnica Add ValueObject info to README
solnic authored
209
210 ``` ruby
211 class GeoLocation
212 include Virtus::ValueObject
213
9ca622f Kristian Mandrup added option to define multiple attributes using deprecated #attributes ...
authored
214 attributes :latitude, :longitude, Float
6d1a987 Piotr Solnica Add ValueObject info to README
solnic authored
215 end
216
217 class Venue
218 include Virtus
219
220 attribute :name, String
221 attribute :location, GeoLocation
222 end
223
224 venue = Venue.new(
225 :name => 'Pub',
226 :location => { :latitude => 37.160317, :longitude => -98.437500 })
227
710f757 Yves Senn inline xmp-comments and use consistent spacing
senny authored
228 venue.location.latitude # => 37.160317
6d1a987 Piotr Solnica Add ValueObject info to README
solnic authored
229 venue.location.longitude # => -98.4375
230
231 # Supports object's equality
232
233 venue_other = Venue.new(
234 :name => 'Other Pub',
235 :location => { :latitude => 37.160317, :longitude => -98.437500 })
236
237 venue.location === venue_other.location # => true
238 ```
239
28a01ee Piotr Solnica Fix headers in README
solnic authored
240 ### Adding Coercions
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
241
242 Virtus comes with a builtin coercion library.
243 It's super easy to add your own coercion classes.
244 Take a look:
245
246 ``` ruby
247 require 'digest/md5'
9bfc2c6 Piotr Solnica README update
solnic authored
248
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
249 # Our new attribute type
250 class MD5 < Virtus::Attribute::Object
251 primitive String
252 coercion_method :to_md5
253 end
6df00da Piotr Solnica Add missing User class to Coercion example in README
solnic authored
254
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
255 # Defining the Coercion method
256 module Virtus
257 class Coercion
258 class String < Virtus::Coercion::Object
259 def self.to_md5(value)
260 Digest::MD5.hexdigest value
261 end
6df00da Piotr Solnica Add missing User class to Coercion example in README
solnic authored
262 end
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
263 end
264 end
6df00da Piotr Solnica Add missing User class to Coercion example in README
solnic authored
265
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
266 # And now the user!
267 class User
268 include Virtus
ceed87f Piotr Solnica README update
solnic authored
269
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
270 attribute :name, String
271 attribute :password, MD5
272 end
ceed87f Piotr Solnica README update
solnic authored
273
b3cfa2e Yves Senn use parentheses when calling methods with arguments (dkubb's styleguide)
senny authored
274 user = User.new(:name => 'Piotr', :password => 'foobar')
710f757 Yves Senn inline xmp-comments and use consistent spacing
senny authored
275 user.name # => 'Piotr'
276 user.password # => '3858f62230ac3c915f300c664312c63f'
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
277 ```
ceed87f Piotr Solnica README update
solnic authored
278
28a01ee Piotr Solnica Fix headers in README
solnic authored
279 ### Custom Attributes
ceed87f Piotr Solnica README update
solnic authored
280
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
281 ``` ruby
282 require 'json'
ceed87f Piotr Solnica README update
solnic authored
283
ef31ea2 Fabio Rehm Update README example to be "copy-and-pastable"
fgrehm authored
284 module MyApp
ceed87f Piotr Solnica README update
solnic authored
285
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
286 # Defining the custom attribute(s)
287 module Attributes
288 class JSON < Virtus::Attribute::Object
289 primitive Hash
290
291 def coerce(value)
292 ::JSON.parse value
ceed87f Piotr Solnica README update
solnic authored
293 end
294 end
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
295 end
296
297 class User
298 include Virtus
ceed87f Piotr Solnica README update
solnic authored
299
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
300 attribute :info, Attributes::JSON
301 end
302 end
ceed87f Piotr Solnica README update
solnic authored
303
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
304 user = MyApp::User.new
710f757 Yves Senn inline xmp-comments and use consistent spacing
senny authored
305 user.info = '{"email":"john@domain.com"}' # => {"email"=>"john@domain.com"}
306 user.info.class # => Hash
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
307 ```
105d4b6 Piotr Solnica Add information about coercions to README file
solnic authored
308
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
309 Credits
310 -------
ddcc8c1 Piotr Solnica Add contributors section to README
solnic authored
311
312 * Dan Kubb ([dkubb](https://github.com/dkubb))
e5d155e Piotr Solnica Oops, sorry Chris :)
solnic authored
313 * Chris Corbyn ([d11wtq](https://github.com/d11wtq))
ddcc8c1 Piotr Solnica Add contributors section to README
solnic authored
314 * Emmanuel Gomez ([emmanuel](https://github.com/emmanuel))
4186272 Piotr Solnica Add fgrehm and mbj to the credits list
solnic authored
315 * Fabio Rehm ([fgrehm](https://github.com/fgrehm))
0ece1f9 Piotr Solnica Add Ryan to the list of the awesome contributors!
solnic authored
316 * Ryan Closner ([rclosner](https://github.com/rclosner))
4186272 Piotr Solnica Add fgrehm and mbj to the credits list
solnic authored
317 * Markus Schirp ([mbj](https://github.com/mbj))
47b8c5a Piotr Solnica Add Yves Senn to the list of contributors
solnic authored
318 * Yves Senn ([senny](https://github.com/senny))
ddcc8c1 Piotr Solnica Add contributors section to README
solnic authored
319
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
320 Contributing
321 -------------
ceed87f Piotr Solnica README update
solnic authored
322
323 * Fork the project.
324 * Make your feature addition or bug fix.
325 * Add tests for it. This is important so I don't break it in a
326 future version unintentionally.
319d1c5 Yves Senn rephrased contribution guidelines to match the project structure
senny authored
327 * Commit, do not mess with Rakefile or version
ceed87f Piotr Solnica README update
solnic authored
328 (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)
329 * Send me a pull request. Bonus points for topic branches.
330
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
331 License
332 -------
333
405ef9d Dan Kubb Update Copyright year
dkubb authored
334 Copyright (c) 2011-2012 Piotr Solnica
4306df1 Using syntax highlighting, clarifying source.
Kurtis Rainbolt-Greene authored
335
336 Permission is hereby granted, free of charge, to any person obtaining
337 a copy of this software and associated documentation files (the
338 "Software"), to deal in the Software without restriction, including
339 without limitation the rights to use, copy, modify, merge, publish,
340 distribute, sublicense, and/or sell copies of the Software, and to
341 permit persons to whom the Software is furnished to do so, subject to
342 the following conditions:
343
344 The above copyright notice and this permission notice shall be
345 included in all copies or substantial portions of the Software.
346
347 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
348 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
349 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
350 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
351 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
352 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
353 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Something went wrong with that request. Please try again.