Flon
Flon, the API maker that uses JSON. It focuses on not doing any magic: it’s just a thin and convenient wrapper over Rack, with a hopefully obvious DSL.
Installation
Add this line to your application's Gemfile:
gem 'flon'
And then execute:
bundle
Or install it yourself as:
gem install flon
Usage
Basic usage
To use Flon, simply make a plain class extending Flon::DSL
. This will put the
router DSL in your class scope.
require 'flon'
class MyAPI
extend Flon::DSL
def initialize
@names = []
end
namespace '/names' do
get '/'
attr_reader :names
post '/new'
def add_name(request)
@names << request.body
end
namespace '/:index' do
get '/'
def name_by_index(request)
@names[request.params[:index].to_i]
end
put '/edit'
def change_name(request)
@names[request.params[:index].to_i] = request.body
end
end
end
end
You can then create a Flon::API
using this:
api = Flon::API.new(MyAPI.new)
Note how you initialise everything normally—you can use this for dependency injection without a headache.
Flon::API
is a bog-standard Rack app, so you can just use it in config.ru
,
or whatever method you use.
Routing
The DSL defines methods for routing based on every HTTP request method, except HEAD, TRACE, OPTIONS, and CONNECT. HEAD is handled by GET routes but the body is discarded.
When you call a routing method, the next method you define will be bound to that route.
get '/route'
def get_route
# matches GET /route and HEAD /route
end
post '/route'
def post_route
# matches POST /route
end
put '/route'
def put_route
# matches PUT /route
end
delete '/route'
def delete_route
# matches DELETE /route
end
patch '/route'
def patch_route
# matches PATCH /route
end
Each routing DSL method takes a single route pattern as a String
. The route
pattern is the exact same as Sinatra’s.
The bound method is called when an HTTP request matches that route with that HTTP method.
The method will receive one argument, the Flon::Request
object describing the
HTTP request:
request.body # Gets the body; returns a String, or nil if no body
request.headers # Gets the headers; returns a Hash with String keys and
# String values
request.method # Gets the HTTP method; returns a Symbol with the name of
# the method lowercased
request.params # Gets the route and query parameters, merged, giving
# priority to route parameters; returns a Hash with Symbol
# keys
request.path # Gets the path; returns a String
request.query_params # Gets the query parameters, specifically; returns a Hash
# with Symbol keys
request.route_params # Gets the route parameters, specifically; returns a Hash
# with Symbol keys
request.url # Gets the request’s URL; returns an URI object
Note that the argument will not be passed if the method does not accept at least one argument, so you can leave it out if you’re not gonna use it.
Namespaces
You can also namespace routes:
namespace '/users' do
get '/'
attr_reader :users # GET /users
post '/new'
def add_user(request) # /users/new
@users << request.body
end
namespace '/:id' do
get
def user_by_id(request) # GET /users/:id
@users[request.params[:id].to_i]
end
put '/edit'
def edit_user(request) # PUT /users/:id/edit
@users[request.params[:id].to_i] = request.body
end
end
end
Namespaces are entirely “virtual”, that is, they just concatenate their route patterns with their children, so they’re just there for DRYness.
Versioning
The version
method applies a namespace throughout every route:
version '/v1'
get '/yes'
def yes
'yes'
end
get '/no'
def no
'no'
end
Going to /yes
will give you a 404, but going to /v1/yes
will give you
"yes"
. The same thing happens with the /no
route.
In reality, version
is just an alias for namespace
.
Responding
Whatever is returned by the route’s method is #to_json
’d and sent back. If
you want to return a custom response, return a Flon::Response
object, which
takes the status code as the first argument, the body as the second argument,
and the headers as the third argument of its constructor:
get '/admin'
def admin
Flon::Response.new(403, 'No. Go away.', 'X-Loser' => 'Yes')
end
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run
rake
to run rubocop and the tests. You can also run bin/console
for an
interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To
release a new version, update the version number in version.rb
, and then run
bundle exec rake release
, which will create a git tag for the version, push
git commits and tags, and push the .gem
file to
rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/unleashy/flon.
License
The gem is available as open source under the terms of the MIT License.