🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

graphiti

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphiti

1.8.2
Rubygems
Version published
Maintainers
1
Created
Source

Graphiti

CI Gem Version Ruby Style Guide semantic-release: angular

discord guides

Graphiti logo Graphiti is a resource-oriented framework that sits on top of your models (usually ActiveRecord) and exposes them via a JSON:API-compliant interface. It abstracts common concerns like serialization, filtering, sorting, pagination, and sideloading relationships, so you can build powerful APIs with minimal boilerplate. By defining resources instead of controllers and serializers, Graphiti helps you keep your API logic organized, consistent, and easy to maintain.

Examples

Here's an example resource from the example app just to give you a taste of the possibilities.

class EmployeeResource < ApplicationResource
  attribute :first_name, :string
  attribute :last_name, :string
  attribute :age, :integer
  attribute :created_at, :datetime, writable: false
  attribute :updated_at, :datetime, writable: false
  attribute :title, :string, only: [:filterable, :sortable]

  has_many :positions
  has_many :tasks
  many_to_many :teams
  polymorphic_has_many :notes, as: :notable
  has_one :current_position, resource: PositionResource do
    params do |hash|
      hash[:filter][:current] = true
    end
  end

  filter :title, only: [:eq] do
    eq do |scope, value|
      scope.joins(:current_position).merge(Position.where(title: value))
    end
  end

  sort :title do |scope, value|
    scope.joins(:current_position).merge(Position.order(title: value))
  end

  sort :department_name, :string do |scope, value|
    scope.joins(current_position: :department)
      .merge(Department.order(name: value))
  end
end

A pretty boilerplate controller that just interfaces with the resource

class EmployeesController < ApplicationController
  def index
    employees = EmployeeResource.all(params)
    respond_with(employees)
  end

  def show
    employee = EmployeeResource.find(params)
    respond_with(employee)
  end

  def create
    employee = EmployeeResource.build(params)

    if employee.save
      render jsonapi: employee, status: 201
    else
      render jsonapi_errors: employee
    end
  end

  def update
    employee = EmployeeResource.find(params)

    if employee.update_attributes
      render jsonapi: employee
    else
      render jsonapi_errors: employee
    end
  end

  def destroy
    employee = EmployeeResource.find(params)

    if employee.destroy
      render jsonapi: { meta: {} }, status: 200
    else
      render jsonapi_errors: employee
    end
  end
end

Now you can query your endpoints simply and powerfully, like:

Request: http://localhost:3000/api/v1/employees?filter[title][eq]=Future Government Administrator&filter[age][lt]=40

JSON-API response
{
  "data": [
    {
      "id": "1",
      "type": "employees",
      "attributes": {
        "first_name": "Quinn",
        "last_name": "Homenick",
        "age": 36,
        "created_at": "2025-03-21T23:04:40+00:00",
        "updated_at": "2025-03-21T23:04:40+00:00"
      },
      "relationships": {
        "positions": {
          "links": {
            "related": "/api/v1/positions?filter[employee_id]=1"
          },
          "data": [
            {
              "type": "positions",
              "id": "1"
            },
            {
              "type": "positions",
              "id": "2"
            }
          ]
        },
        "tasks": {
          "links": {
            "related": "/api/v1/tasks?filter[employee_id]=1"
          }
        },
        "teams": {
          "links": {
            "related": "/api/v1/teams?filter[employee_id]=1"
          }
        },
        "notes": {
          "links": {
            "related": "/api/v1/notes?filter[notable_id]=1&filter[notable_type][eql]=Employee"
          }
        },
        "current_position": {
          "links": {
            "related": "/api/v1/positions?filter[current]=true&filter[employee_id]=1"
          },
          "data": {
            "type": "positions",
            "id": "1"
          }
        }
      }
    }
  ],
  "included": [
    {
      "id": "1",
      "type": "positions",
      "attributes": {
        "title": "Future Government Administrator",
        "active": true
      },
      "relationships": {
        "employee": {
          "links": {
            "related": "/api/v1/employees/1"
          }
        },
        "department": {
          "links": {
            "related": "/api/v1/departments/3"
          }
        }
      }
    },
    {
      "id": "2",
      "type": "positions",
      "attributes": {
        "title": "Manufacturing Specialist",
        "active": false
      },
      "relationships": {
        "employee": {
          "links": {
            "related": "/api/v1/employees/1"
          }
        },
        "department": {
          "links": {
            "related": "/api/v1/departments/2"
          }
        }
      }
    }
  ],
  "meta": {}
}

Graphiti Guides

Join the Discord

FAQs

Package last updated on 20 May 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

OSZAR »