README.md in u-attributes-2.0.1 vs README.md in u-attributes-2.1.0

- old
+ new

@@ -1,23 +1,43 @@ -![Ruby](https://img.shields.io/badge/ruby-2.2+-ruby.svg?colorA=99004d&colorB=cc0066) -[![Gem](https://img.shields.io/gem/v/u-attributes.svg?style=flat-square)](https://rubygems.org/gems/u-attributes) -[![Build Status](https://travis-ci.com/serradura/u-attributes.svg?branch=main)](https://travis-ci.com/serradura/u-attributes) -[![Maintainability](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/maintainability)](https://codeclimate.com/github/serradura/u-attributes/maintainability) -[![Test Coverage](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/test_coverage)](https://codeclimate.com/github/serradura/u-attributes/test_coverage) +<p align="center"> + <img src="./assets/u-attributes_logo_v1.png" alt='Create "immutable" objects. No setters, just getters!'> -μ-attributes (Micro::Attributes) <!-- omit in toc --> -================================ + <p align="center"><i>Create "immutable" objects. No setters, just getters!</i></p> + <br> +</p> +<p align="center"> + <img src="https://img.shields.io/badge/ruby-2.2+-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby"> + + <a href="https://rubygems.org/gems/u-attributes"> + <img alt="Gem" src="https://img.shields.io/gem/v/u-attributes.svg?style=flat-square"> + </a> + + <a href="https://travis-ci.com/serradura/u-attributes"> + <img alt="Build Status" src="https://travis-ci.com/serradura/u-attributes.svg?branch=main"> + </a> + + <a href="https://codeclimate.com/github/serradura/u-attributes/maintainability"> + <img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/maintainability"> + </a> + + <a href="https://codeclimate.com/github/serradura/u-attributes/test_coverage"> + <img alt="Test Coverage" src="https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/test_coverage"> + </a> +</p> + This gem allows you to define "immutable" objects, and your objects will have only getters and no setters. So, if you change [[1](#with_attribute)] [[2](#with_attributes)] some object attribute, you will have a new object instance. That is, you transform the object instead of modifying it. -## Table of contents <!-- omit in toc --> +# Table of contents <!-- omit in toc --> - [Installation](#installation) - [Compatibility](#compatibility) - [Usage](#usage) - [How to define attributes?](#how-to-define-attributes) - [`Micro::Attributes#attributes=`](#microattributesattributes) + - [How to extract attributes from an object or hash?](#how-to-extract-attributes-from-an-object-or-hash) + - [Is it possible to define an attribute as required?](#is-it-possible-to-define-an-attribute-as-required) - [`Micro::Attributes#attribute`](#microattributesattribute) - [`Micro::Attributes#attribute!`](#microattributesattribute-1) - [How to define multiple attributes?](#how-to-define-multiple-attributes) - [`Micro::Attributes.with(:initialize)`](#microattributeswithinitialize) - [`#with_attribute()`](#with_attribute) @@ -53,24 +73,24 @@ # Compatibility | u-attributes | branch | ruby | activemodel | | -------------- | ------- | -------- | ------------- | -| 2.0.0 | main | >= 2.2.0 | >= 3.2, < 6.1 | +| 2.1.0 | main | >= 2.2.0 | >= 3.2, < 6.1 | | 1.2.0 | v1.x | >= 2.2.0 | >= 3.2, < 6.1 | > **Note**: The activemodel is an optional dependency, this module [can be enabled](#activemodelvalidation-extension) to validate the attributes. [⬆️ Back to Top](#table-of-contents-) # Usage ## How to define attributes? -```ruby -# By default you must to define the class constructor. +By default, you must define the class constructor. +```ruby class Person include Micro::Attributes attribute :age attribute :name @@ -114,10 +134,70 @@ person.age # 20 person.name # John Doe ``` +#### How to extract attributes from an object or hash? + +You can extract attributes using the `extract_attributes_from` method, it will try to fetch attributes from the +object using either the `object[attribute_key]` accessor or the reader method `object.attribute_key`. + +```ruby +class Person + include Micro::Attributes + + attribute :age + attribute :name, default: 'John Doe' + + def initialize(user:) + self.attributes = extract_attributes_from(user) + end +end + +# extracting from an object + +class User + attr_accessor :age, :name +end + +user = User.new +user.age = 20 + +person = Person.new(user: user) + +person.age # 20 +person.name # John Doe + +# extracting from a hash + +another_person = Person.new(user: { age: 55, name: 'Julia Not Roberts' }) + +another_person.age # 55 +another_person.name # Julia Not Roberts +``` + +#### Is it possible to define an attribute as required? + +You only need to use the `required: true` option. + +But to this work, you need to assign the attributes using the [`#attributes=`](#microattributesattributes) method or the extensions: [initialize](#initialize-extension), [activemodel_validations](#activemodelvalidation-extension). + +```ruby +class Person + include Micro::Attributes + + attribute :age + attribute :name, required: true + + def initialize(attributes) + self.attributes = attributes + end +end + +Person.new(age: 32) # ArgumentError (missing keyword: :name) +``` + [⬆️ Back to Top](#table-of-contents-) ### `Micro::Attributes#attribute` Use this method with a valid attribute name to get its value. @@ -183,11 +263,11 @@ ```ruby class Person include Micro::Attributes.with(:initialize) - attribute :age + attribute :age, required: true attribute :name, default: 'John Doe' end person = Person.new(age: 18) @@ -256,12 +336,14 @@ [⬆️ Back to Top](#table-of-contents-) ## The strict initializer -Use `.with(initialize: :strict)` to forbids an instantiation without all the attribute keywords. e.g. +Use `.with(initialize: :strict)` to forbids an instantiation without all the attribute keywords. +In other words, it is equivalent to you define all the attributes using the [`required: true` option](#is-it-possible-to-define-an-attribute-as-required). + ```ruby class StrictPerson include Micro::Attributes.with(initialize: :strict) attribute :age @@ -366,9 +448,15 @@ Person.attribute?(:foo) # false # --- person = Person.new(age: 20) + +#---------------------# +# #defined_attributes # +#---------------------# + +person.defined_attributes # ['name', 'age'] #---------------# # #attribute?() # #---------------#