Encore is a Ruby framework to help dealing with entities.
---
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'encore'
```
And then execute:
```bash
$ bundle
```
Or install it yourself as:
```bash
$ gem install encore
```
## Usage
Let’s say we have the `UserEntity` entity class bound to the `User` model:
```ruby
class User < ActiveRecord::Base
end
class UserEntity
include Encore::Entity
expose :name
expose :email
expose :created_at, readonly: true
expose :updated_at, readonly: true
end
```
We can create a new `User` resource with attributes:
```ruby
@entity = UserEntity.new
@entity.assign_attributes email: 'remi@example.com', name: 'Rémi Prévost'
@entity.save
```
When assigning attributes to an entity, we can pass either an `:update` or a `:partial_update` context.
With the (default) `:partial_update` context, Encore will assign new attributes and ignore the other exposed attributes. This makes sense in a `PATCH` HTTP request context.
```ruby
new_attributes = { email: 'remi+new@example.com' }
@entity.assign_attributes new_attributes
@entity.object.email # => "remi+new@example.com"
@entity.object.name # => "Rémi Prévost"
```
However, with the `:update` context, Encore will assign new attributes and set all non-provided exposed attributes to `nil`. This
makes sense in a `PUT` HTTP request context.
```ruby
new_attributes = { email: 'remi+new-again@example.com' }
@entity.assign_attributes new_attributes, context: :update
@entity.object.email # => "remi+new-again@example.com"
@entity.object.name # => nil
```
If we try to assign a value to a non-exposed or readonly attribute, Encore will raise an error.
```ruby
@entity.assign_attributes email: 'remi+new@example.com', created_at: Time.now
# => raises # attribute is not exposed.>
```
### Associations
You can also expose associations.
```ruby
class User < ActiveRecord::Base
belongs_to :organization
end
class Organization < ActiveRecord::Base
has_many :users
end
class UserEntity
include Encore::Entity
expose :name
expose_one :organization
end
```
Assigning new value for associations doesn’t save them right away.
```ruby
@user = User.first # => #
@entity = UserEntity.new(@user)
@entity.assign_attributes organization: 2
@entity.object.organization_id # => 1
```
Calling `save` on the entity saves them.
```ruby
@entity.save
@entity.object.organization_id # => 2
```
## Typical setup with Ruby on Rails
_This is work-in-progress. There’s still missing stuff._
### Model
```ruby
# app/models/user.rb
class User < ActiveRecord::Base
end
```
### Entity
```ruby
# app/entities/user_entity.rb
class UserEntity
include Encore::Entity
expose :name
expose :email
expose :created_at, readonly: true
expose :updated_at, readonly: true
end
```
### Routes
```ruby
# config/routes.rb
Rails::Application.routes.draw do
resources :users do
# This makes Rails route PUT and PATCH requests to two separate actions
patch on: :member, action: :partial_update
end
end
```
### Controller
```ruby
# app/controllers/users_controller.rb
class UsersController < ApplicationController
before_action :fetch_user, only: [:update, :partial_update]
# POST /users
def create
@entity = UserEntity.new
@entity.assign_attributes(params[:user], context: :create)
process! @entity
# Here, `process!` is a shortcut for:
#
# if @entity.save
# render json: @entity, status: 201
# else
# render json: { errors: @entity.errors }, status: 422
# end
end
# PUT /users/:id
def update
@entity = UserEntity.new(@user)
@entity.assign_attributes(params[:user], context: :update)
process! @entity
end
# PATCH /users/:id
def partial_update
@entity = UserEntity.new(@user)
@entity.assign_attributes(params[:user], context: :partial_update)
process! @entity
end
protected
def fetch_user
@user = User.find(params[:id])
end
end
```
## Todo
Please keep in mind that this gem is far from finished and totally not ready to use in production.
This is something we’ve been wanting to build for a long time and now we’re finally taking the time
do it right.
## License
`Encore` is © 2013 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/encore/blob/master/LICENSE.md) file.
The nut logo is based on [this lovely icon](http://thenounproject.com/noun/hazelnuts/#icon-No3618) by [Alessandro Suraci](http://thenounproject.com/alessandro.suraci/), from The Noun Project. Used under a [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/) license.
## About Mirego
Mirego is a team of passionate people who believe that work is a place where you can innovate and have fun. We proudly build mobile applications for [iPhone](http://mirego.com/en/iphone-app-development/ "iPhone application development"), [iPad](http://mirego.com/en/ipad-app-development/ "iPad application development"), [Android](http://mirego.com/en/android-app-development/ "Android application development"), [Blackberry](http://mirego.com/en/blackberry-app-development/ "Blackberry application development"), [Windows Phone](http://mirego.com/en/windows-phone-app-development/ "Windows Phone application development") and [Windows 8](http://mirego.com/en/windows-8-app-development/ "Windows 8 application development") in beautiful Quebec City.
We also love [open-source software](http://open.mirego.com/) and we try to extract as much code as possible from our projects to give back to the community.