1 From Scratch

The easiest way to start from scratch is to use the application template:

$ rails new blog --api -m https://raw.githubusercontent.com/graphiti-api/graphiti_rails_template/master/all.rb

Alternatively, download and point to the template locally:

$ curl -O https://raw.githubusercontent.com/graphiti-api/graphiti_rails_template/master/all.rb
$ rails new blog --api -m all.rb

Run git diff to see the changes to a blank Rails app.

2 Adding to an Existing App

This process is straightforward; you can add Graphiti to an existing Rails app alongside JBuilder or ActiveModelSerializers.

Start with gems:

# The only strictly-required gem
gem 'graphiti'

# For automatic ActiveRecord pagination
gem 'kaminari'

# Test-specific gems
group :development, :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'faker'
  gem 'graphiti_spec_helpers'
end

group :test do
  gem 'database_cleaner'
end

You’ll be up-and-running at this point. Verify with a simple standalone Resource:

# Assuming you already have a Post ActiveRecord Model
class PostResource < Graphiti::Resource
  self.adapter = Graphiti::Adapters::ActiveRecord
  attribute :title, :string
end

PostResource.all.data # => [#<Post>, #<Post>, ...]

Now we just need to integrate with Rails endpoints (to give us things like #context):

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include Graphiti::Rails
end

And wire-up our error-handling:

# app/controllers/application_controller.rb
# When #show action does not find record, return 404
register_exception Graphiti::Errors::RecordNotFound,
  status: 404

rescue_from Exception do |e|
  handle_exception(e)
end

That’s it for the basics. You may have issues with generators conflicting with your existing application structure - but you can always write files manually or submit an issue.

2.1 Responders

Graphiti supports JSONAPI, simple JSON, and XML. You can do this manually when inheriting from ActionController::Base

def index
  posts = PostResource.all(params)

  respond_to do |format|
    format.json { render(json: posts) }
    format.jsonapi { render(jsonapi: posts) }
    format.xml { render(xml: posts) }
  end
end

But we can inherit from ActionController::API while avoiding this boilerplate with with the Responders gem:

def index
  posts = PostResource.all(params)
  respond_with(posts)
end

To get this functionality:

# Gemfile
gem 'responders'

# app/controllers/application_controller.rb
include Graphiti::Responders

Note: Persistence operations only support JSONAPI format, so you’ll still use render jsonapi: and render jsonapi_errors: for those.

2.3 .graphiticfg.yml

The .graphiticfg.yml file lives in the root directory of your application. It holds configuration we need to reuse across a variety of contexts (primarily generates and rake tasks). If you use our template to create your application, it’s created for you.

Primarily this is used to hold your “API namespace”:

---
namespace: /my_api/v1

If this file doesn’t exist you may get unexpected errors - make sure to create it!

2.4 Testing

To add our Integration Tests:

# Gemfile
group :development, :test do
  gem 'graphiti_spec_helpers'
  gem 'factory_bot_rails'
  gem 'rspec_rails'
  gem 'faker'
end

group :test do
  gem 'database_cleaner'
end

Bootstrap RSpec if you haven’t already:

$ bin/rails g rspec:install

Add some RSpec configuration:

require 'graphiti_spec_helpers/rspec'

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
  config.include GraphitiSpecHelpers::RSpec
  config.include GraphitiSpecHelpers::Sugar

  # Raise errors during tests by default
  config.before :each do
    GraphitiErrors.disable!
  end

  # Clean your DB between test runs
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    begin
      DatabaseCleaner.cleaning do
        example.run
      end
    ensure
      DatabaseCleaner.clean
    end
  end
end

2.5 will_paginate

By default, we use Kaminari for ActiveRecord pagination. If you prefer [will_paginate] (or anything else):

# app/resources/application_resource.rb
paginate do |scope, current_page, per_page|
  scope.paginate(page: current_page, per_page: per_page)
end

3 Without Rails

You can use Graphiti in any plain .rb file. To see this in action, check out the Plain Ruby Sample App.