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