README.md in lotus-validations-0.0.0 vs README.md in lotus-validations-0.1.0
- old
+ new
@@ -1,9 +1,31 @@
# Lotus::Validations
-TODO: Write a gem description
+Validations mixins for objects
+## Status
+
+[![Gem Version](http://img.shields.io/gem/v/lotus-validations.svg)](https://badge.fury.io/rb/lotus-validations)
+[![Build Status](http://img.shields.io/travis/lotus/validations/master.svg)](https://travis-ci.org/lotus/validations?branch=master)
+[![Coverage](http://img.shields.io/coveralls/lotus/validations/master.svg)](https://coveralls.io/r/lotus/validations)
+[![Code Climate](http://img.shields.io/codeclimate/github/lotus/validations.svg)](https://codeclimate.com/github/lotus/validations)
+[![Dependencies](http://img.shields.io/gemnasium/lotus/validations.svg)](https://gemnasium.com/lotus/validations)
+[![Inline Docs](http://inch-ci.org/github/lotus/validations.svg)](http://inch-ci.org/github/lotus/validations)
+
+## Contact
+
+* Home page: http://lotusrb.org
+* Mailing List: http://lotusrb.org/mailing-list
+* API Doc: http://rdoc.info/gems/lotus-validations
+* Bugs/Issues: https://github.com/lotus/validations/issues
+* Support: http://stackoverflow.com/questions/tagged/lotus-ruby
+* Chat: https://gitter.im/lotus/chat
+
+## Rubies
+
+__Lotus::Validations__ supports Ruby (MRI) 2+ and JRuby 1.7 (with 2.0 mode).
+
## Installation
Add this line to your application's Gemfile:
```ruby
@@ -18,14 +40,355 @@
$ gem install lotus-validations
## Usage
-TODO: Write usage instructions here
+`Lotus::Validations` is a set of lightweight validations for Ruby objects.
+### Attributes
+
+The framework allows you to define attributes for each object.
+
+It defines an initializer, whose attributes can be passed as a hash.
+All unknown values are ignored, which is useful for whitelisting attributes.
+
+```ruby
+require 'lotus/validations'
+
+class Person
+ include Lotus::Validations
+
+ attribute :name
+end
+
+person = Person.new(name: 'Luca', age: 32)
+person.name # => "Luca"
+person.age # => raises NoMethodError because `:age` wasn't defined as attribute.
+```
+
+### Coercions
+
+If a Ruby class is passed to the `:type` option, the given value is coerced, accordingly.
+
+#### Standard coercions
+
+```ruby
+require 'lotus/validations'
+
+class Person
+ include Lotus::Validations
+
+ attribute :fav_number, type: Integer
+end
+
+person = Person.new(fav_number: '23')
+person.valid?
+
+person.fav_number # => 23
+```
+
+Allowed types are:
+
+ * `Array`
+ * `BigDecimal`
+ * `Boolean`
+ * `Date`
+ * `DateTime`
+ * `Float`
+ * `Hash`
+ * `Integer`
+ * `Pathname`
+ * `Set`
+ * `String`
+ * `Symbol`
+ * `Time`
+
+#### Custom coercions
+
+If a user defined class is specified, it can be freely used for coercion purposes.
+The only limitation is that the constructor should have **arity of 1**.
+
+```ruby
+require 'lotus/validations'
+
+class FavNumber
+ def initialize(number)
+ @number = number
+ end
+end
+
+class BirthDate
+end
+
+class Person
+ include Lotus::Validations
+
+ attribute :fav_number, type: FavNumber
+ attribute :date, type: BirthDate
+end
+
+person = Person.new(fav_number: '23', date: 'Oct 23, 2014')
+person.valid?
+
+person.fav_number # => 23
+person.date # => this raises an error, because BirthDate#initialize doesn't accept any arg
+```
+
+### Validations
+
+Each attribute definition can receive a set of options to define one or more
+validations.
+
+**Validations are triggered when you invoke `#valid?`.**
+
+#### Acceptance
+
+An attribute is valid if it's value satisfies [Ruby's _truthiness_](http://ruby.about.com/od/control/a/Boolean-Expressions.htm).
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ include Lotus::Validations
+
+ attribute :terms_of_service, acceptance: true
+end
+
+signup = Signup.new(terms_of_service: '1')
+signup.valid? # => true
+
+signup = Signup.new(terms_of_service: '')
+signup.valid? # => false
+```
+
+#### Confirmation
+
+An attribute is valid if it's value and the value of a corresponding attribute
+is valid.
+
+By convention, if you have a `password` attribute, the validation looks for `password_validation`.
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ include Lotus::Validations
+
+ attribute :password, confirmation: true
+end
+
+signup = Signup.new(password: 'secret', password_confirmation: 'secret')
+signup.valid? # => true
+
+signup = Signup.new(password: 'secret', password_confirmation: 'x')
+signup.valid? # => false
+```
+
+#### Exclusion
+
+An attribute is valid, if the value isn't excluded from the value described by
+the validator.
+
+The validator value can be anything that responds to `#include?`.
+In Ruby, this includes most of the core objects: `String`, `Enumerable` (`Array`, `Hash`,
+`Range`, `Set`).
+
+See also [Inclusion](#inclusion).
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ include Lotus::Validations
+
+ attribute :music, exclusion: ['pop']
+end
+
+signup = Signup.new(music: 'rock')
+signup.valid? # => true
+
+signup = Signup.new(music: 'pop')
+signup.valid? # => false
+```
+
+#### Format
+
+An attribute is valid if it matches the given Regular Expression.
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ include Lotus::Validations
+
+ attribute :name, format: /\A[a-zA-Z]+\z/
+end
+
+signup = Signup.new(name: 'Luca')
+signup.valid? # => true
+
+signup = Signup.new(name: '23')
+signup.valid? # => false
+```
+
+#### Inclusion
+
+An attribute is valid, if the value provided is included in the validator's
+value.
+
+The validator value can be anything that responds to `#include?`.
+In Ruby, this includes most of the core objects: like `String`, `Enumerable` (`Array`, `Hash`,
+`Range`, `Set`).
+
+See also [Exclusion](#exclusion).
+
+```ruby
+require 'prime'
+require 'lotus/validations'
+
+class PrimeNumbers
+ def initialize(limit)
+ @numbers = Prime.each(limit).to_a
+ end
+
+ def include?(number)
+ @numbers.include?(number)
+ end
+end
+
+class Signup
+ include Lotus::Validations
+
+ attribute :age, inclusion: 18..99
+ attribute :fav_number, inclusion: PrimeNumbers.new(100)
+end
+
+signup = Signup.new(age: 32)
+signup.valid? # => true
+
+signup = Signup.new(age: 17)
+signup.valid? # => false
+
+signup = Signup.new(fav_number: 23)
+signup.valid? # => true
+
+signup = Signup.new(fav_number: 8)
+signup.valid? # => false
+```
+
+#### Presence
+
+An attribute is valid if present.
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ include Lotus::Validations
+
+ attribute :name, presence: true
+end
+
+signup = Signup.new(name: 'Luca')
+signup.valid? # => true
+
+signup = Signup.new(name: '')
+signup.valid? # => false
+
+signup = Signup.new(name: nil)
+signup.valid? # => false
+```
+
+#### Size
+
+An attribute is valid if it's `#size` falls within the described value.
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ MEGABYTE = 1024 ** 2
+ include Lotus::Validations
+
+ attribute :ssn, size: 11 # exact match
+ attribute :password, size: 8..64 # range
+ attribute :avatar, size 1..(5 * MEGABYTE)
+end
+
+signup = Signup.new(password: 'a-very-long-password')
+signup.valid? # => true
+
+signup = Signup.new(password: 'short')
+signup.valid? # => false
+```
+
+**Note that in the example above you are able to validate the weight of the file,
+because Ruby's `File` and `Tempfile` both respond to `#size`.**
+
+#### Uniqueness
+
+Uniqueness validations aren't implemented because this library doesn't deal with persistence.
+The other reason is that this isn't an effective way to ensure uniqueness of a value in a database.
+
+Please read more at: [The Perils of Uniqueness Validations](http://robots.thoughtbot.com/the-perils-of-uniqueness-validations).
+
+### Complete example
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ include Lotus::Validations
+
+ attribute :first_name, presence: true
+ attribute :last_name, presence: true
+ attribute :email, presence: true, format: /\A(.*)@(.*)\.(.*)\z/
+ attribute :password, presence: true, confirmation: true, size: 8..64
+end
+```
+
+### Errors
+
+When you invoke `#valid?`, validations errors are available at `#errors`.
+It's a set of errors grouped by attribute. Each error contains the name of the
+invalid attribute, the failed validation, the expected value and the current one.
+
+```ruby
+require 'lotus/validations'
+
+class Signup
+ include Lotus::Validations
+
+ attribute :email, presence: true, format: /\A(.*)@(.*)\.(.*)\z/
+ attribute :age, size: 18..99
+end
+
+signup = Signup.new(email: 'user@example.org')
+signup.valid? # => true
+
+signup = Signup.new(email: '', age: 17)
+signup.valid? # => false
+
+signup.errors
+ # => #<Lotus::Validations::Errors:0x007fe00ced9b78
+ # @errors={
+ # :email=>[
+ # #<Lotus::Validations::Error:0x007fe00cee3290 @attribute=:email, @validation=:presence, @expected=true, @actual="">,
+ # #<Lotus::Validations::Error:0x007fe00cee31f0 @attribute=:email, @validation=:format, @expected=/\A(.*)@(.*)\.(.*)\z/, @actual="">
+ # ],
+ # :age=>[
+ # #<Lotus::Validations::Error:0x007fe00cee30d8 @attribute=:age, @validation=:size, @expected=18..99, @actual=17>
+ # ]
+ # }>
+```
+
## Contributing
-1. Fork it ( https://github.com/[my-github-username]/lotus-validations/fork )
+1. Fork it ( https://github.com/lotus/lotus-validations/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
+
+## Copyright
+
+Copyright 2014 Luca Guidi – Released under MIT License