README.md in transmutation-0.2.2 vs README.md in transmutation-0.2.3

- old
+ new

@@ -1,22 +1,32 @@ # Transmutation Transmutation is a Ruby gem that provides a simple way to serialize Ruby objects into JSON. -It takes inspiration from the [Active Model Serializers](https://github.com/rails-api/active_model_serializers) gem, but strips away adapters. +It also adds an opinionated way to automatically find and use serializer classes based on the object's class name and the caller's namespace - it takes inspiration from the [Active Model Serializers](https://github.com/rails-api/active_model_serializers) gem, but strips away adapters. It aims to be a performant and elegant solution for serializing Ruby objects into JSON, with a touch of opinionated "magic" :sparkles:. ## Installation -Install the gem and add to the application's Gemfile by executing: +Install the gem and add to your application's Gemfile by executing: - $ bundle add transmutation +```bash +bundle add transmutation +``` +or manually add the following to your Gemfile: + +```ruby +gem "transmutation" +``` + If bundler is not being used to manage dependencies, install the gem by executing: - $ gem install transmutation +```bash +gem install transmutation +``` ## Usage ### Basic Usage @@ -46,17 +56,20 @@ UserSerializer.new(user).to_json # => "{\"id\":1,\"name\":\"John Doe\",\"email\":\"john@example.com\"}" ``` As long as your object responds to the attributes defined in the serializer, it can be serialized. - - Struct + <details> + <summary>Struct</summary> ```ruby User = Struct.new(:id, :name, :email) ``` + </details> - - Class + <details> + <summary>Class</summary> ```ruby class User attr_reader :id, :name, :email @@ -65,12 +78,14 @@ @name = name @email = email end end ``` + </details> - - ActiveRecord + <details> + <summary>ActiveRecord</summary> ```ruby # == Schema Information # # Table name: users @@ -79,17 +94,144 @@ # name :string # email :string class User < ApplicationRecord end ``` + </details> -### Using the `Transmutation::Serialization` module +### The `#serialize` method +When you include the `Transmutation::Serialization` module in your class, you can use the `#serialize` method to serialize an object. + +It will attempt to find a serializer class based on the object's class name along with the caller's namespace. + +```ruby +include Transmutation::Serialization + +serialize(User.new) # => UserSerializer.new(User.new) +``` + +If no serializer class is found, it will return the object as is. + +### With Ruby on Rails + +When then `Transmutation::Serialization` module is included in a Rails controller, it also extends your `render` calls. + +```ruby +class Api::V1::UsersController < ApplicationController + include Transmutation::Serialization + + def show + user = User.find(params[:id]) + + render json: user + end +end +``` + +This will attempt to bubble up the controller namespaces to find a defined serializer class: + +- `Api::V1::UserSerializer` +- `Api::UserSerializer` +- `UserSerializer` + +This calls the `#serialize` method under the hood. + +If no serializer class is found, it will fall back to the default behavior of rendering the object as JSON. + +You can disable this behaviour by passing `serialize: false` to the `render` method. + +```ruby +render json: user, serialize: false # => user.to_json +``` + +## Configuration + +You can override the serialization lookup by passing the following options: + +- `namespace`: The namespace to use when looking up the serializer class. + + ```ruby + render json: user, namespace: "V1" # => Api::V1::V1::UserSerializer + ``` + + To prevent caller namespaces from being appended to the provided namespace, prefix the namespace with `::`. + + ```ruby + render json: user, namespace: "::V1" # => V1::UserSerializer + ``` + + The `namespace` key is forwarded to the `#serialize` method. + + ```ruby + render json: user, namespace: "V1" # => serialize(user, namespace: "V1") + ``` + +- `serializer`: The serializer class to use. + + ```ruby + render json: user, serializer: "SuperUserSerializer" # => Api::V1::SuperUserSerializer + ``` + + To prevent all namespaces from being appended to the serializer class, prefix the serializer class with `::`. + + ```ruby + render json: user, serializer: "::SuperUserSerializer" # => SuperUserSerializer + ``` + + The `serializer` key is forwarded to the `#serialize` method. + + ```ruby + render json: user, serializer: "SuperUserSerializer" # => serialize(user, serializer: "SuperUserSerializer") + ``` + +## Opinionated Architecture + +If you follow the pattern outlined below, you can take full advantage of the automatic serializer lookup. + +### File Structure + +``` +. +└── app/ + ├── controllers/ + │ └── api/ + │ ├── v1/ + │ │ └── users_controller.rb + │ └── v2 + │ └── users_controller.rb + ├── models/ + │ └── user.rb + └── serializers/ + └── api/ + ├── v1/ + │ └── user_serializer.rb + ├── v2/ + │ └── user_serializer.rb + └── user_serializer.rb +``` + +### Serializers + +```ruby +class Api::UserSerializer < Transmutation::Serializer + attributes :id, :name, :email +end + +class Api::V1::UserSerializer < Api::UserSerializer + attributes :phone # Added in V1 +end + +class Api::V2::UserSerializer < Api::UserSerializer + attributes :avatar # Added in V2 +end +``` + +To remove attributes, it is recommended to redefine all attributes and start anew. This acts as a reset and makes serializer inheritance much easier to follow. + ## 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 the created tag, 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/spellbook-technology/transmutation. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/spellbook-technology/transmutation/blob/main/CODE_OF_CONDUCT.md).