CollectionJson::Serializer

Build Status

:warning: This is not finished yet, so use it at your own risk.

A Ruby gem to respond with Collection+JSON.

CollectionJson::Serializer formats JSON responses following the Collection+JSON media type by Mike Amudsen.

Please note that CollectionJson::Serializer only serializes data. You still need to set the proper Headers or media-types in your app.

Installation

Add this line to your application's Gemfile:

gem 'collection_json_serializer'

And then execute:

$ bundle

Or install it yourself as:

$ gem install collection_json_serializer

Usage

As this gem user, you will be mainly writing/generating and mantaining serializers for your models. A serializer goes like:

class UserSerializer < CollectionJson::Serializer
  href self: "http://example.com/users/1",
       collection: "http://example.com/users"

  attributes :id, name: { prompt: "Your full name" }, :email

  template :name, email: { prompt: "My email" }

  # Please note that links can only be passed as hashes
  links dashboard: { href: "http://example.com/my-dashboard" }

  queries search: {
    href: "http://example.com/search",
    name: false # Don't automatically include the name attribute
  }, pagination: {
    rel: "page",
    href: "http://example.com/page",
    prompt: "Select a page number",
    data: [
      { name: "page" }
    ]
  }
end

Then, you pass your objects to the serializer:

@user = User.new(name: "Carles Jove", email: "[email protected]")

# Pass it to the serializer
user_serializer = UserSerializer.new(@user)

# You can also pass an array of objects
# user_serializer = UserSerializer.new([@user1, @user2, etc])

# Pass the serializer to the builder
collection = CollectionJson::Serializer::Builder.new(user_serializer)
collection.to_json

# You can get the collection as a hash, too
collection.pack
# => { collection: { version: "1.0" } }

This will generate this Collection+JSON response:

{ "collection": 
  {
    "version" : "1.0",
    "href" : "http://example.com/users",
    "items" : [{
      "href": "http://example.com/users/1",
      "data": [
        { "name": "id", "value": "1" },
        { "name": "name", "value": "Carles Jove", "prompt": "Your full name" },
        { "name": "email", "value": "[email protected]" },
      ],
      "links": [
        { "name": "dashboard", "href": "http://example.com/my-dashboard" }
      ]
    }],
    "template" : {
      "data": [
        { "name": "name", "value": "" },
        { "name": "email", "value": "", "prompt": "My email" }
      ]
    },
    "queries": [{
      "rel": "search",
      "href": "http://example.com/search"
    },{
      "rel": "page",
      "href": "http://example.com/page",
      "name": "pagination",
      "prompt": "Select a page number",
      "data": [
        { "name": "page", "value": "" }
      ]
    }]
  }
}

URL placeholders

URLs can be generated dinamically with placeholder. A placeholder is a URL segment wrapped in curly braces. A placeholder can be any method that can be called on the object that the serializer takes (i.e. id, username, etc.).

class UserSerializer < CollectionJson::Serializer
  href self: "http://example.com/users/{id}"
end

All placeholders will be called, so you can use more than one if necessary, but you may use only one placeholer per segment.

class UserSerializer < CollectionJson::Serializer
  # This is ok
  href self: "http://example.com/users/{id}/{username}"

  # This is not ok
  href self: "http://example.com/users/{id}-{username}"
end

Open Attributes Policy

Collection+JSON serializer has an open attributes policy, which means that objects' attributes can be extended at will. That is good if you want to use many of the extensions available, and also if you need to add custom extensions to suit your particular needs. Be aware that, as the specs say, you must only extend attributes in a way that won't break clients that are not aware of them.

class UserSerializer < CollectionJson::Serializer
  attributes :id, name: { css_class: "people" }

  template name: { regex: "/\A[a-zA-Z0-9_]*\z/" }

  links profile: { css_class: "button" }
end

Contributing

  1. Fork it ( https://github.com/[my-github-username]/collection_json_serializer/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request