GithubHelp home page GithubHelp logo

gregschmit / rails-rest-framework Goto Github PK

View Code? Open in Web Editor NEW
41.0 4.0 2.0 1.68 MB

A framework for DRY RESTful APIs in Ruby on Rails.

Home Page: https://rails-rest-framework.com

License: MIT License

Ruby 82.51% Shell 0.71% HTML 16.27% Dockerfile 0.44% Procfile 0.07%
rails api rest restful-api

rails-rest-framework's Introduction

Rails REST Framework

Gem Version Pipeline Coverage Maintainability

A framework for DRY RESTful APIs in Ruby on Rails.

The Problem: Building controllers for APIs usually involves writing a lot of redundant CRUD logic, and routing them can be obnoxious. Building and maintaining features like ordering, filtering, and pagination can be tedious.

The Solution: This framework implements browsable API responses, CRUD actions for your models, and features like ordering/filtering/pagination, so you can focus on building awesome APIs.

Website/Guide: rails-rest-framework.com

Demo API: rails-rest-framework.com/api/demo

Source: github.com/gregschmit/rails-rest-framework

YARD Docs: rubydoc.info/gems/rest_framework

Installation

Add this line to your application's Gemfile:

gem "rest_framework"

And then run:

bundle install

Quick Usage Tutorial

This section provides some simple examples to quickly get you started using the framework.

For the purpose of this example, you'll want to add an api_controller.rb to your controllers, as well as a directory for the resources:

controllers/
├─ api_controller.rb
└─ api/
   ├─ root_controller.rb
   ├─ movies_controller.rb
   └─ users_controller.rb

Controller Mixins

The root ApiController can include any common behavior you want to share across all your API controllers:

class ApiController < ApplicationController
  include RESTFramework::BaseControllerMixin

  # Setting up a paginator class here makes more sense than defining it on every child controller.
  self.paginator_class = RESTFramework::PageNumberPaginator

  # The page_size attribute doesn't exist on the `BaseControllerMixin`, but for child controllers
  # that include the `ModelControllerMixin`, they will inherit this attribute and will not overwrite
  # it.
  class_attribute(:page_size, default: 30)
end

A root controller can provide actions that exist on the root of your API. It's best to define a dedicated root controller, rather than using the ApiController for this purpose, so that actions don't propagate to child controllers:

class Api::RootController < ApiController
  self.extra_actions = {test: :get}

  def root
    return api_response(
      {
        message: "Welcome to the API.",
        how_to_authenticate: <<~END.lines.map(&:strip).join(" "),
          You can use this API with your normal login session. Otherwise, you can insert your API
          key into a Bearer Authorization header, or into the URL parameters with the name
          `api_key`.
        END
      },
    )
  end

  def test
    return api_response({message: "Hello, world!"})
  end
end

And here is an example of a resource controller:

class Api::MoviesController < ApiController
  include RESTFramework::ModelControllerMixin

  self.fields = [:id, :name, :release_date, :enabled]
  self.extra_member_actions = {first: :get}

  def first
    # Always use the bang method, since the framework will rescue `RecordNotFound` and return a
    # sensible error response.
    return api_response(self.get_records.first!)
  end

  def get_recordset
    return Movie.where(enabled: true)
  end
end

When fields is nil, then it will default to all columns. The fields attribute can also be a hash to include or exclude fields rather than defining them manually:

class Api::UsersController < ApiController
  include RESTFramework::ModelControllerMixin

  self.fields = {include: [:calculated_popularity], exclude: [:impersonation_token]}
end

Routing

Use rest_route for non-resourceful controllers, or rest_resource / rest_resources resourceful routers. These routers add some features to the Rails builtin resource/resources routers, such as automatically routing extra actions defined on the controller. To route the root, use rest_root.

Rails.application.routes.draw do
  # If you wanted to route actions from the `ApiController`, then you would use this:
  # rest_root :api  # Will find `api_controller` and route the `root` action to '/api'.

  namespace :api do
    rest_root  # Will route `Api::RootController#root` to '/' in this namespace ('/api').
    rest_resources :movies
    rest_resources :users
  end
end

Development/Testing

After you clone the repository, cd'ing into the directory should create a new gemset if you are using RVM. Then run bin/setup to install the appropriate gems and set things up.

The top-level bin/rails proxies all Rails commands to the test project, so you can operate it via the usual commands (e.g., rails test, rails server and rails console). For development, use foreman start to run the web server and the job queue.

rails-rest-framework's People

Contributors

dependabot[bot] avatar gregschmit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

rails-rest-framework's Issues

Flesh out OPTIONS API

We currently support sending fields metadata, but we should also communicate the available actions (including and making distinction for member actions) on a controller. We should also coerce more validations to top-level information on the fields metadata.

Batch processing

Consider adding ability to create, update, or delete multiple records at once. Perhaps there is a configuration option to determine if this is done using efficient SQL operations without callbacks/validation, or less efficient ORM operations with callbacks/validation.

Support ordering/filtering by association properties

Probably by a designated column, but perhaps by specifying the target column, but then the issue is whether the user should have access to that column. So probably just by a designated column (perhaps name by default?).

Display allowed params (with field config) in browsable API

For most CRUD it's just the default fields, but like for DELETE it should be nothing, and then for extra fields it should just be fields defined in their config... probably?

Either way, need to be able to say "for this extra action, here are the params that are acceptable".

Use `includes` more intelligently.

Right now, we include all associations in the model controller mixin. Rather, we should allow filters to include what they need to avoid including associations unnecessarily.

Greater than/less than filtering?

On your website for this it shows being able to filter with =, is there a built in way to > or <. I have been beating my head against the wall for the better part of a day trying to figure it out.

So looking for something like https://mysite/api/movies?id>255

Just and example. what im trying to do is filter between 2 dates.

PUT behaves like PATCH

Issuing an update to a record via PUT behaves like PATCH, updating only the sent properties instead of completely replacing the record as would be expected. This mostly manifests when a nullable field was not originally null, but is desired to be nulled, and a PUT with new property values is sent without a null for that property.

Potentially consider a way to make PUT behave as expected, or indicate that PUT behaves like PATCH

Websockets

There is already a branch for this, but basically I want to dynamically construct ::Channel classes on each controller to allow subscribing to updates for a particular collection, and interacting with controller endpoints via action cable (or anycable).

Delegate API

We should support delegating extra actions to the underlying model for the ModelControllerMixin. Collection actions can be delegated to the model, and member actions can be delegated to records. We should either enable this via configuration or provide a configuration option in the extra_actions/extra_member_actions configuration API.

HABTM relationships

I was looking into what it would take for an external API client to instrument PMS Guest <> Room relationships and was struggling so I looked into the RRF source and I think this change might address the issue:

image

I can always do a "1-off" in the specific controller to make the specific field accessible, but I was wondering if there had ever been consideration of making all HABTM relationships addressable like this?

So far I've only tested this inside a 1-off scenario like this, and it seems to work as intended:

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.