/shreddies

Stupid simple Rails model and object serializer

Primary LanguageRubyMIT LicenseMIT

Shreddies - Stupid simple Rails model and object serializer

Shreddies is a JSON serialization library for Rails that focuses on simplicity and speed. No more "magic" DSL's - just plain old Ruby objects! It's primarily intended to serialize Rails models as JSON, but will also work with pretty much anything at all.

Shreddies primary principle is to be explicit. So a serializer will return nothing until you define some methods. This gives you complete control and everything is a known quantity - no surprises.

Installation

Add this line to your application's Gemfile:

gem 'shreddies'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install shreddies

Usage

Serializers should be named after your models and located in "app/serializers". Any public methods you define will be serialized, and you can quickly expose methods from the serialized subject using the delegate class method, which simply delegates to the subject.

# app/serializers/user_serializer.rb
class UserSerializer < Shreddies::Json
  delegate :id, :first_name, :last_name, :email

  def name
    "#{first_name} #{last_name}"
  end
end

Calling the above will result in this JSON:

{
  "id": 1,
  "name": "Joel Moss",
  "firstName": "Joel",
  "lastName": "Moss",
  "email": "me@you.com"
}

NOTE that all keys are transformed to camelCase, as the JSON is intended to be used by Javascript.

Call your serializer directly:

UserSerializer.render(user)

Or just use the #as_json instance method on your model:

User.find(1).as_json

Model collections and array's are also supported:

User.all.as_json

Collection and Single Modules

You may find that you don't want or need to return as much data in collections of objects, or may want to include differtent data. So if a serializer defines a Collection module, and a collection or array is being rendered, then that Collection module will automatically be included:

ArticleSerializer < Shreddies::Json
  module Collection
    def url
      "https://blah.com/#{subject.slug}"
    end
  end
end

Conversely, you can define a Single module, and that will be included when rendering a single object.

ArticleSerializer < Shreddies::Json
  module Single
    def body
      'this body is really, really long, and I do not want it returned in lists.'
    end
  end
end

ActiveRecord Associations

ActiveRecord associations are supported with no additional work on your part. Shreddies will simply call #as_json on any method that returns an ActiveRecord model or relation.

# app/serializers/user_serializer.rb
class UserSerializer < Shreddies::Json
  delegate :articles

  def latest_article
    articles.latest
  end
end

And if you need to be specific about what you render, just call the serializer or #as_json directly:

# app/serializers/user_serializer.rb
class UserSerializer < Shreddies::Json
  def articles
    subject.articles.as_json index_by: :slug
  end

  def latest_article
    LatestArticleSerializer.render articles.latest
  end
end

before_render callback

You can define a #before_render private method in your serializers, which will act as a callback. It receives the object to be output, and expects you to return the object, which allows you to modify it before rendering.

Options

Both #as_json and .render accepts an options hash, which will be forwarded to the serializer class, and available as options. This allows you to pass arbitrary options and use them in your serializer.

The following standard options are supported, and provide additional built-in functionality:

serializer

By default #as_json will look for a serializer named after your model. So a User model will automatically use the UserSerializer. Sometimes you want to use a different serializer class, in which case you can use the serializer option:

User.all.as_json serializer: User::AdminSerializer

module

You can pass one or module names in the module option, and these modules will be included into the serializer. This is great for selectively including attributes and methods.

Article.all.as_json module: :WithBody
ArticleSerializer < Shreddies::Json
  module WithBody
    def body
      'This article body is really, really long'
    end
  end
end

The Collection and Single modules can be defined and they will be automatically included. The Collection module will be included when rendering an array or ActiveRecord collection (ActiveRecord::Relation), and the Single module will be included when rendering a single obejct.

transform_keys (default: true)

If false, the returned keys will not be transformed. The default is to deeply transform all keys to camelCase.

except

Pass one or more attribute names as a Symbol or Array of Symbols, and these will be excluded from the results:

User.all.as_json(except: [:first_name, :age])

only

Pass one or more attribute names as a Symbol or Array of Symbols, and ONLY these will be included in the results:

User.all.as_json(only: :first_name)

Attributes must still be defined within the Serializer.

index_by

Give this option a property of your serialized subject as a Symbol, and the returned collection will be a Hash keyed by that property.

User.all.as_json index_by: :id
{
  1: {
    "id": 1,
    "name": "Joel Moss",
    "firstName": "Joel",
    "lastName": "Moss"
  }

  2: {
    "id": 2,
    "name": "An Other",
    "firstName": "An",
    "lastName": "Other"
  }

  ...
}

Serializer Inheritance

A serializer can inherit from any other serializer, which is a great way to create custom views:

# app/serializers/user_serializer.rb
class UserSerializer < Shreddies::Json
  delegate :id, :first_name, :last_name, :email

  def name
    "#{first_name} #{last_name}"
  end
end

class User::AdministratorSerializer < UserSerializer
  def type
    'administrator'
  end
end

Then call it like any other serializer:

User::AdministratorSerializer.render(user)

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test 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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/joelmoss/shreddies. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Shreddies project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.