darthjee/azeroth

View on GitHub
README.md

Summary

Maintainability
Test Coverage
Azeroth
========
[![Build Status](https://circleci.com/gh/darthjee/azeroth.svg?style=shield)](https://circleci.com/gh/darthjee/azeroth)
[![Code Climate](https://codeclimate.com/github/darthjee/azeroth/badges/gpa.svg)](https://codeclimate.com/github/darthjee/azeroth)
[![Test Coverage](https://codeclimate.com/github/darthjee/azeroth/badges/coverage.svg)](https://codeclimate.com/github/darthjee/azeroth/coverage)
[![Issue Count](https://codeclimate.com/github/darthjee/azeroth/badges/issue_count.svg)](https://codeclimate.com/github/darthjee/azeroth)
[![Gem Version](https://badge.fury.io/rb/azeroth.svg)](https://badge.fury.io/rb/azeroth)
[![Inline docs](http://inch-ci.org/github/darthjee/azeroth.svg)](http://inch-ci.org/github/darthjee/azeroth)

![azeroth](https://raw.githubusercontent.com/darthjee/azeroth/master/azeroth.jpg)

Yard Documentation
-------------------
[https://www.rubydoc.info/gems/azeroth/1.1.0](https://www.rubydoc.info/gems/azeroth/1.1.0)

Azeroth has been designed making the coding of controllers easier
as routes in controllers are usually copy, paste and replace of same
code.

Azeroth was originally developed for controller actions
which will respond with json or template rendering based
on the requested format `.json` or `.html` where `html` rendering
does not perform database operations

Future versions will enable `html` rendering to also perform
database operations.

Current Release: [1.1.0](https://github.com/darthjee/azeroth/tree/1.1.0)

[Next release](https://github.com/darthjee/azeroth/compare/1.1.0...master)

Installation
---------------

- Install it

```ruby
  gem install azeroth
```

- Or add Sinclair to your `Gemfile` and `bundle install`:

```ruby
  gem 'azeroth'
```

```bash
  bundle install azeroth
```

Usage
-----

## Azeroth::Resourceable

[Resourceable](https://www.rubydoc.info/gems/azeroth/Azeroth/Resourceable)
module adds class method [resource_for](https://www.rubydoc.info/gems/azeroth/Azeroth/Resourceable/ClassMethods#resource_for-instance_method)
which adds a resource and action methods for `create`, `show`, `index`,
`update`, `delete`, `edit`

It accepts options
- only: List of actions to be built
- except: List of actions to not to be built
- decorator: Decorator class or flag allowing/disallowing decorators
- before_save: Method/Proc to be ran before saving the resource on create or update
- after_save: Method/Proc to be ran after saving the resource on create or update
- build_with: Method/Block to be ran when building the reource on create
- update_with: Method/Block to be ran when updating the reource on update
- paginated: Flag when pagination should be applied
- per_page: Number of items returned when pagination is active

```ruby
  # publishers_controller.rb

  class PublishersController < ApplicationController
    include Azeroth::Resourceable
    skip_before_action :verify_authenticity_token

    resource_for :publisher, only: %i[create index]
  end
```

```ruby
  # games_controller.rb

  class GamesController < ApplicationController
    include Azeroth::Resourceable
    skip_before_action :verify_authenticity_token

    resource_for :game, except: :delete

    private

    def games
      publisher.games
    end

    def publisher
      @publisher ||= Publisher.find(publisher_id)
    end

    def publisher_id
      params.require(:publisher_id)
    end
  end
```

```ruby
  # pokemons_controller.rb

  class PokemonsController < ApplicationController
    include Azeroth::Resourceable

    resource_for :pokemon,
                 only: %i[create update],
                 before_save: :set_favorite

    private

    def set_favorite
      pokemon.favorite = true
    end

    def pokemons
      master.pokemons
    end

    def master
      @master ||= PokemonMaster.find(master_id)
    end

    def master_id
      params.require(:pokemon_master_id)
    end
  end
```

```ruby
  class PaginatedDocumentsController < ApplicationController
    include Azeroth::Resourceable

    resource_for :document, only: 'index', paginated: true
  end

  30.times { create(:document) }

  get '/paginated_documents.json'

  # returns Array with 20 first documents
  # returns in the headers pagination headers
  # {
  #   'pages' => 2,
  #   'per_page' => 20,
  #   'page' => 1
  # }

  get '/paginated_documents.json?page=2'

  # returns Array with 10 next documents
  # returns in the headers pagination headers
  # {
  #   'pages' => 2,
  #   'per_page' => 20,
  #   'page' => 2
  # }
```

## Azeroth::Decorator

[Decorators](https://www.rubydoc.info/gems/azeroth/Azeroth/Decorator) are
used to define how an object is exposed as json on controller responses
defining which and how fields will be exposed

Exposing options:

- as: custom key to expose the value as
- if: method/block to be called checking if an attribute should or should not be exposed
- decorator: flag to use or not a decorator or decorator class to be used
- reader: Flag indicating if a reader to access the attribute should be created. usefull if you want method_missing to take over
- override: Flag indicating if an existing method should be overriden. This is useful when a method acessor was included from another module

```ruby
  # pokemon/decorator.rb

  class Pokemon::Decorator < Azeroth::Decorator
    expose :name
    expose :previous_form_name, as: :evolution_of, if: :evolution?

    def evolution?
      previous_form
    end

    def previous_form_name
      previous_form.name
    end
  end
```

```ruby
  # pokemon/favorite_decorator.rb

  class Pokemon::FavoriteDecorator < Pokemon::Decorator
    expose :nickname
  end
```

```ruby
  # pokemon_master/decorator.rb

  class PokemonMaster < ActiveRecord::Base
    has_one :favorite_pokemon, -> { where(favorite: true) },
            class_name: 'Pokemon'
    has_many :pokemons
  end
```

Exposing is done through the class method
[expose](https://www.rubydoc.info/gems/azeroth/Azeroth/Decorator#expose-class_method)
which accepts several options:

- as: custom key to expose
- if: method/block to be called checking if an attribute should or should not be exposed
- decorator: flag to use or not a decorator or decorator class to be used