README.md in shallow_attributes-0.9.0 vs README.md in shallow_attributes-0.9.2
- old
+ new
@@ -1,20 +1,22 @@
# ShallowAttributes
[![Build Status](https://travis-ci.org/davydovanton/shallow_attributes.svg?branch=master)](https://travis-ci.org/davydovanton/shallow_attributes)
[![Code Climate](https://codeclimate.com/github/davydovanton/shallow_attributes/badges/gpa.svg)](https://codeclimate.com/github/davydovanton/shallow_attributes)
+[![Coverage Status](https://coveralls.io/repos/github/davydovanton/shallow_attributes/badge.svg?branch=master)](https://coveralls.io/github/davydovanton/shallow_attributes?branch=master)
[![Inline docs](http://inch-ci.org/github/davydovanton/shallow_attributes.svg?branch=master)](http://inch-ci.org/github/davydovanton/shallow_attributes)
-Simple and lightweight Virtus analog.
+Simple and lightweight Virtus analog without any dependencies. [Documentation][doc-link].
## Motivation
-There are already a lot of good and flexible gems which solve a similar problem, allowing attributes to be
-defined with their types, for example: virtus, fast_attributes or attrio. However, the disadvantage of these
-gems is performance or API. So, the goal of ShallowAttributes is to provide a simple solution which is similar
-to the Virtus API, simple, fast, understandable and extendable.
+There are already a lot of good and flexible gems which solve a similar problem, allowing attributes
+to be defined with their types, for example: [virtus][virtus-link], [fast_attributes][fast-attributes-link]
+or [attrio][attrio-link]. However, the disadvantage of these gems is performance or API. So, the goal
+of `ShallowAttributes` is to provide a simple solution which is similar to the `Virtus` API, simple, fast,
+understandable and extendable.
-This is [the performance benchmark](https://gist.github.com/davydovanton/7cf0da532eae71381cbd) of ShallowAttributes compared to virtus gems.
+This is [the performance benchmark][performance-benchmark] of ShallowAttributes compared to virtus gems.
## Installation
Add this line to your application's Gemfile:
@@ -29,10 +31,19 @@
Or install it yourself as:
$ gem install shallow_attributes
## Examples
+### Table of contents
+* [Using ShallowAttributes with Classes](#using-shallowattributes-with-classes)
+* [Default Values](#default-values)
+* [Embedded Value](#embedded-value)
+* [Custom Coercions](#custom-coercions)
+* [Collection Member Coercions](#collection-member-coercions)
+* [Note about Member Coercions](#important-note-about-member-coercions)
+* [Overriding setters](#overriding-setters)
+* [ActiveModel validation](#activemodel-validation)
### Using ShallowAttributes with Classes
You can create classes extended with Virtus and define attributes:
```ruby
@@ -51,27 +62,27 @@
attribute :age, Integer, allow_nil: true
attribute :birthday, DateTime
end
user = User.new(name: 'Anton', age: 31)
-user.name # => "Anton"
+user.name # => "Anton"
user.age = '31' # => 31
-user.age = nil # => nil
-user.age.class # => Fixnum
+user.age = nil # => nil
+user.age.class # => Fixnum
user.birthday = 'November 18th, 1983' # => #<DateTime: 1983-11-18T00:00:00+00:00 (4891313/2,0/1,2299161)>
user.attributes # => { name: "Anton", age: 31, birthday: nil }
# mass-assignment
user.attributes = { name: 'Jane', age: 21 }
-user.name # => "Jane"
-user.age # => 21
+user.name # => "Jane"
+user.age # => 21
super_user = SuperUser.new
-user.age = nil # => 0
+user.age = nil # => 0
```
### Default Values
``` ruby
@@ -107,11 +118,11 @@
page.views # => 10
page.reset_attribute(:views) # => 0
page.views # => 0
```
-## Embedded Value
+### Embedded Value
``` ruby
class City
include ShallowAttributes
@@ -140,11 +151,11 @@
city: {
name: 'NYC'
}
})
-user.address.street # => "Street 1/2"
+user.address.street # => "Street 1/2"
user.address.city.name # => "NYC"
```
### Custom Coercions
@@ -163,11 +174,11 @@
attribute :info, Json, default: {}
end
user = User.new
user.info = '{"email":"john@domain.com"}' # => {"email"=>"john@domain.com"}
-user.info.class # => Hash
+user.info.class # => Hash
# With a custom attribute encapsulating coercion-specific configuration
class NoisyString
def coerce(value, options = {})
value.to_s.upcase
@@ -226,21 +237,55 @@
{ :number => '919-444-3265' } ],
:addresses => [
{ :address => '1234 Any St.', :locality => 'Anytown', :region => "DC", :postal_code => "21234" } ])
user.phone_numbers # => [#<PhoneNumber:0x007fdb2d3bef88 @number="212-555-1212">, #<PhoneNumber:0x007fdb2d3beb00 @number="919-444-3265">]
-user.addresses # => [#<Address:0x007fdb2d3be448 @address="1234 Any St.", @locality="Anytown", @region="DC", @postal_code="21234">]
+user.addresses # => [#<Address:0x007fdb2d3be448 @address="1234 Any St.", @locality="Anytown", @region="DC", @postal_code="21234">]
-user.attributes # => {
- # => :phone_numbers => [
- # => { :number => '212-555-1212' },
- # => { :number => '919-444-3265' } ],
- # => :addresses => [
- # => { :address => '1234 Any St.', :locality => 'Anytown', :region => "DC", :postal_code => "21234" } ]
- # => }
+user.attributes
+# => {
+# => :phone_numbers => [
+# => { :number => '212-555-1212' },
+# => { :number => '919-444-3265' }
+# => ],
+# => :addresses => [
+# => {
+# => :address => '1234 Any St.',
+# => :locality => 'Anytown',
+# => :region => "DC",
+# => :postal_code => "21234"
+# => }
+# => ]
+# => }
```
+### IMPORTANT note about member coercions
+
+ShallowAttributes performs coercions only when a value is being assigned. If you mutate the value later on using its own interfaces then coercion won't be triggered.
+
+Here's an example:
+
+``` ruby
+class Book
+ include ShallowAttributes
+ attribute :title, String
+end
+
+class Library
+ include ShallowAttributes
+ attribute :books, Array, of: Book
+end
+
+library = Library.new
+
+# This will coerce Hash to a Book instance
+library.books = [ { :title => 'Introduction' } ]
+
+# This WILL NOT COERCE the value because you mutate the books array with Array#<<
+library.books << { :title => 'Another Introduction' }
+```
+
### Overriding setters
``` ruby
class User
include ShallowAttributes
@@ -284,22 +329,33 @@
user.valid? # => true
```
## Ruby version support
-ShallowAttributes is known to work correctly with the following rubies:
+ShallowAttributes is [known to work correctly][travis-link] with the following rubies:
-* 2.3+
+* 2.0
+* 2.1
+* 2.2
+* 2.3
+* 2.4
+* jruby-head
-In future I want ot support other ruby sersion/platforms.
+Also we run rbx-2 buld too.
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/davydovanton/shallow_attributes.
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected
to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
-
## License
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
+
+[doc-link]: http://www.rubydoc.info/github/davydovanton/shallow_attributes/master
+[virtus-link]: https://github.com/solnic/virtus
+[fast-attributes-link]: https://github.com/applift/fast_attributes
+[attrio-link]: https://github.com/jetrockets/attrio
+[performance-benchmark]: https://gist.github.com/davydovanton/d14b51ab63e3fab63ecb
+[travis-link]: https://travis-ci.org/davydovanton/shallow_attributes