elabs/serial

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# Serial

[![Build Status](https://travis-ci.org/elabs/serial.svg?branch=master)](http://travis-ci.org/elabs/serial)
[![Dependency Status](https://gemnasium.com/elabs/serial.svg)](https://gemnasium.com/elabs/serial)
[![Code Climate](https://codeclimate.com/github/elabs/serial/badges/gpa.svg)](https://codeclimate.com/github/elabs/serial)
[![Gem Version](https://badge.fury.io/rb/serial.svg)](http://badge.fury.io/rb/serial)
[![Inline docs](http://inch-ci.org/github/elabs/serial.svg?branch=master&style=shields)](http://inch-ci.org/github/elabs/serial)

*Psst, full documentation can be found at [rubydoc.info/gems/serial](http://www.rubydoc.info/gems/serial)*

Serial is a light-weight and simple serialization library. Its primary purpose is to generate primitive
datastructures from object graphs, in other words to help you serialize your data.

Serial is sponsored by [Elabs][].

[![elabs logo][]][Elabs]

[Elabs]: http://www.elabs.se/
[elabs logo]: ./elabs-logo.png?raw=true

## Installation

Add this line to your application's Gemfile:

```ruby
gem "serial"
```

And then execute:

    $ bundle

## The DSL

*Full reference: [Serial::HashBuilder](http://www.rubydoc.info/gems/serial/Serial/HashBuilder), [Serial::ArrayBuilder](http://www.rubydoc.info/gems/serial/Serial/ArrayBuilder).*

- All keys are turned into strings.
- There is no automatic camel-casing. You name your keys the way you want them.
- Using the same key twice will raise an error by default.
- To override the value for an existing key, use the respective !-method DSL, i.e. `#attribute!`, `#collection!`, `#map!`, or `#merge!`.

### Simple attributes

`#attribute` creates a simple attribute with a value.

``` ruby
ProjectSerializer = Serial::Serializer.new do |h, project|
  h.attribute(:id, project.id)
  h.attribute(:displayName, project.display_name)
end # => { "id" => …, "displayName" => … }
```

### Nested attributes

`#attribute` supports nesting by giving it a block.

``` ruby
ProjectSerializer = Serial::Serializer.new do |h, project|
  h.attribute(:owner, project.owner) do |h, owner|
    h.attribute(:name, owner.name)
  end
end # => { "owner" => { "name" => … } }
```

### Collections

`#map` is a convenient method for serializing lists of items.

``` ruby
ProjectSerializer = Serial::Serializer.new do |h, project|
  h.map(:assignments, project.assignments) do |h, assignment|
    h.attribute(:id, assignment.id)
    h.attribute(:duration, assignment.duration)
  end
end # => { "assignments" => [{ "id" => …, "duration" => … }, …] }
```

The low-level interface powering `#map` is `#collection`.

``` ruby
ProjectSerializer = Serial::Serializer.new do |h, project|
  h.collection(:indices) do |l|
    l.element { |h| h.attribute(…)  }
    l.element { |h| h.attribute(…)  }

    l.collection do |l|
      l.element { … }
      l.element { … }
    end
  end
end # => { "indices" => [{…}, {…}, [{…}, {…}]] }
```

### Merging

`#merge` will let you merge another serializer without introducing a new nesting level.

``` ruby
ProjectSerializer = Serial::Serializer.new do |h, project|
  h.attribute(:name, project.name)
end # => { "name" => … }

FullProjectSerializer = Serial::Serializer.new do |h, project|
  h.merge(project, &ProjectSerializer)
  h.attribute(:description, project.description)
end # { "name" => …, "description" => … }
```

### Composition

You can compose serializers by passing them as blocks to the DSL methods.

``` ruby
PersonSerializer = Serial::Serializer.new do |h, person|
  h.attribute(:name, person.name)
end # => { "name" => … }

ProjectSerializer = Serial::Serializer.new do |h, project|
  h.attribute(:owner, project.owner, &PersonSerializer)
  h.map(:people, project.people, &PersonSerializer)
end # { "owner" => { "name" => … }, "people" => [{ "name" => … }, …] }
```

## Using your serializers

*Full reference: [Serial::Serializer](http://www.rubydoc.info/gems/serial/Serial/Serializer).*

- The context parameter in the below examples (when using `#call` and `#map`) is optional, if not provided regular block scoping rules apply.
- Tip: include [Serial::RailsHelpers](http://www.rubydoc.info/gems/serial/Serial/RailsHelpers) in ApplicationController for a convenient `#serialize` method.

### Serializing a single object

``` ruby
project = Project.find(…)
context = self
ProjectSerializer.call(context, project) # => { … }
```

### Serializing a list of objects

``` ruby
projects = Project.all
context = self
ProjectSerializer.map(context, projects) # => [{ … }, …]
```

### Using with Rails

```ruby
# app/serializers/project_serializer.rb
ProjectSerializer = Serial::Serializer.new do |h, project|
  …
end
```

``` ruby
# app/controllers/project_controller.rb
class ProjectController < ApplicationController
  include Serial::RailsHelpers

  def show
    project = Project.find(…)

    # 1. Using helper from RailsHelpers.
    render json: serialize(project)

    # 2. Explicitly mentioning serializer using helper method.
    render json: serialize(project, &ProjectSerializer)

    # 3. Explicitly mentioning serializer.
    render json: ProjectSerializer.call(self, project)
  end
end
```

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run
`rake spec` to run the tests. You can also run `bin/console` for an interactive
prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`. To
release a new version, update the version number in `version.rb`, and then run
`bundle exec rake release`, which will create a git tag for the version, push
git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

Bug reports and pull requests are welcome on GitHub at
https://github.com/elabs/serial. This project is intended to be a safe,
welcoming space for collaboration, and contributors are expected to adhere to
the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct.

## License

The gem is available as open source under the terms of the
[MIT License](http://opensource.org/licenses/MIT).