README.md in shallow_attributes-0.9.2 vs README.md in shallow_attributes-0.9.3

- old
+ new

@@ -1,6 +1,7 @@ # 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) @@ -12,17 +13,17 @@ 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][performance-benchmark] 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: -```ruby +``` ruby gem 'shallow_attributes' ``` And then execute: @@ -31,24 +32,29 @@ 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) +* [Mandatory Attributes](#mandatory-attributes) * [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) +* [ActiveModel compatibility](#activemodel-compatibility) +* [Dry-types](#dry-types) ### Using ShallowAttributes with Classes + You can create classes extended with Virtus and define attributes: -```ruby +``` ruby class User include ShallowAttributes attribute :name, String attribute :age, Integer @@ -81,10 +87,35 @@ super_user = SuperUser.new user.age = nil # => 0 ``` +ShallowAttributes doesn't make any assumptions about base classes. There is no need to define +default attributes, or even mix ShallowAttributes into the base class: + +``` ruby +require 'active_model' + +class Form + extend ActiveModel::Naming + extend ActiveModel::Translation + include ActiveModel::Conversion + include ShallowAttributes + + def persisted? + false + end +end + +class SearchForm < Form + attribute :name, String +end + +form = SearchForm.new(name: 'Anton') +form.name # => "Anton" +``` + ### Default Values ``` ruby class Page include ShallowAttributes @@ -101,10 +132,12 @@ attribute :slug, String, default: lambda { |page, attribute| page.title.downcase.gsub(' ', '-') } # default from a method name as symbol attribute :editor_title, String, default: :default_editor_title + private + def default_editor_title published ? title : "UNPUBLISHED: #{title}" end end @@ -118,10 +151,26 @@ page.views # => 10 page.reset_attribute(:views) # => 0 page.views # => 0 ``` +### Mandatory attributes +You can provide `present: true` option for any attribute that will prevent class from initialization +if this attribute was not provided: + +``` ruby +class CreditCard + include ShallowAttributes + attribute :number, Integer, present: true + attribute :owner, String, present: true +end + +card = CreditCard.new(number: 1239342) +# => ShallowAttributes::MissingAttributeError: Mandatory attribute "owner" was not provided +``` + + ### Embedded Value ``` ruby class City include ShallowAttributes @@ -258,11 +307,12 @@ # => } ``` ### 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. +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 @@ -308,15 +358,60 @@ user = User.new(name: "Godzilla") user.name # => 'Can't tell' ``` -### ActiveModel validation +### ActiveModel compatibility +ShallowAttributes is fully compatible with ActiveModel. + +#### Form object + ``` ruby require 'active_model' +class SearchForm + extend ActiveModel::Naming + extend ActiveModel::Translation + include ActiveModel::Conversion + include ShallowAttributes + + attribute :name, String + attribute :service_ids, Array, of: Integer + attribute :archived, 'Boolean', default: false + + def persisted? + false + end + + def results + # ... + end +end + +class SearchesController < ApplicationController + def index + search_params = params.require(:search_form).permit(...) + @search_form = SearchForm.new(search_params) + end +end +``` + +``` erb +<h1>Search</h1> +<%= form_for @search_form do |f| %> + <%= f.text_field :name %> + <%= f.collection_check_boxes :service_ids, Service.all, :id, :name %> + <%= f.select :archived, [['Archived', true], ['Not Archived', false]] %> +<% end %> +``` + +#### Validations + +``` ruby +require 'active_model' + class Children include ShallowAttributes include ActiveModel::Validations attribute :scream, String @@ -327,10 +422,30 @@ user.valid? # => false user.scream = 'hello world!' user.valid? # => true ``` +### Dry-types +You can use dry-types objects as a type for your attribute: +```ruby +module Types + include Dry::Types.module +end + +class User + include ShallowAttributes + + attribute :name, Types::Coercible::String + attribute :age, Types::Coercible::Int + attribute :birthday, DateTime +end + +user = User.new(name: nil, age: 0) +user.name # => '' +user.age # => 0 +``` + ## Ruby version support ShallowAttributes is [known to work correctly][travis-link] with the following rubies: * 2.0 @@ -349,10 +464,9 @@ 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