Installation
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:
andrender 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.