Restable
Building a REST API — even with Rails — is tedious work. This project aims to eliminate all that tedious work by providing the generic boilerplate functionality that all APIs require so that you can start building out your custom business logic right away. Some aspects of building a REST API in Rails are trivial, in which case guidance on best practices will be provided. Think of Restable as a combination of open-source code and tutorials.
This project is highly inspired by ideas and concepts found in the Stripe API and Shopify API, and aims to allow you to build APIs of similar quality with as little work as possible.
Building Blocks
Rather that lock you into using a custom DSL or particular architecture, RestEasy will expose opt-in functionality through concerns, helpers, etc. and suggest patterns for organizing your code. Think of RestEasy as a tiny framework for building REST APIs rather than a drop-in, pre-packaged solution.
Planned Features
Management of API Secrets & generating secure token- Authentication with basic and bearer token
- Consistent error handling
- JSON Serialization of API resources using JBuilder
- Versioning encouraged through convention over configuration
Potential Future Features
- Pagination with Kaminari
- Webhook delivery to Endpoints
- Generators for quickly scaffolding a new API resource
- RSpec helpers for testing your API
- Request logging
- Expanding responses
- Request IDs and logging
- Rate limiting
- Admin monitoring dashboard
- Documentation generator
Usage
API Credentials
One of the first things you need to do when developing a REST API is create a model to represent authentication credentials. Rails has an excellent has_secure_token
module that handles creation of (surprise!) secure tokens. Restable includes a Restable::SecureToken
concern that can be included into your model that provides some additional functionality, like presence and uniqueness validation of the token
attribute.
We're going to call our credential model Api::SecretKey
. Let's imagine our app has an Account
model, and an account can have many secret keys. Let's generate the model:
rails generate model api/secret_key token:token account:references
👉 Tip: If you want to use the Restable::SecureToken
concern, your token column must be named token
.
The command above will generate app/models/api/secret_key.rb
and the associated migration. Rails will add a unique index on token
to the migration, but it's a good idea to also add a null: false
constraint to that column:
diff --git create_api_secret_keys.rb create_api_secret_keys.rb
index 32c4a68..0b1702e 100644
--- create_api_secret_keys.rb
+++ create_api_secret_keys.rb
@@ -1,11 +1,11 @@
class CreateApiSecretKeys < ActiveRecord::Migration[7.0]
def change
create_table :api_secret_keys do |t|
- t.string :token
+ t.string :token, null: false
t.references :account, null: false, foreign_key: true
t.timestamps
end
add_index :api_secret_keys, :token, unique: true
end
end
The model file generated by Rails will already include has_secure_token
. You can remove this and include Restable::SecureToken
if you like:
# app/models/api/secret_key.rb
class Api::SecretKey < ApplicationRecord
include Restable::SecureToken
belongs_to :account
end
and add the has_many
to your Account
model:
# app/models/account.rb
class Account < ApplicationRecord
has_many :api_secret_keys, dependent: :delete_all, class_name: "Api::SecretKey"
end
Run db:migrate
and your credential system should be ready to go:
account = Account.first
secret_key = account.api_secret_keys.create!
# => <Api::SecretKey:0x00000001077190f0 id: 13, token: "[FILTERED]", account_id: 2, created_at: Fri, 14 Jul 2023 16:44:52.462608000 UTC +00:00, updated_at: Fri, 14 Jul 2023 16:44:52.462608000 UTC +00:00>
secret_key.token
# => "api_secret_key_yLt4AM6S9RQK9Y1C6kYvJZ8w"
Someting to notice is the "api_secret_key"
token prefix. Restable::SecureToken
automatically adds this prefix by singularizing the table name. You can change the prefix by overriding the secure_token_prefix
class method:
class Api::SecretKey < ApplicationRecord
include Restable::SecureToken
def self.secure_token_prefix
# Generate tokens in the format "secret_key_yLt4AM6S9RQK9Y1C6kYvJZ8w"
"secret_key"
end
end
You can disable the prefix by having secure_token_prefix
return nil
.
Of course, because Api::SecretKey
is just a normal Rails model, you can add whatever additional functionality you want to it, like an expires_at
timestamp, a created_by
attribute to track the user who generated the toke, etc. Or maybe your Account
model should only have a single secret key, in which case you can specify has_one :api_secret_key
instead of has_many :api_secret_keys
.
You can also create as many credential model types as you need. For example, if you want to dispatch signed webhooks you could create a Webhook::Signature
model using the same Restable::SecureToken
approach.
Installation
Add this line to your application's Gemfile:
gem "restable"
And then execute:
$ bundle
Or install it yourself as:
$ gem install restable
Contributing
Contributions are welcome.
License
The gem is available as open source under the terms of the MIT License.