Kawaii

Kawaii is a simple web framework based on Rack.

* This is work in progress. The API is subject to change. *

Installation

Add this line to your application's Gemfile:

gem 'kawaii-core'

And then execute:

$ bundle

Or install it yourself as:

$ gem install kawaii-core

Running examples

The /examples directory contains various basic usage examples.

Run the examples using rackup or directly:

$ cd examples
$ rackup -r kawaii modular.ru

Many examples can also be run directly without rackup, e.g.:

$ cd examples
$ ruby -r kawaii hello_world.rb

## Getting started

Kawaii's basic usage is very similar how you'd use Sinatra. You can define route handlers at the file scope. Here's an example:

require 'kawaii'

get '/' do 'Hello, world!' end “`

Save it to hello.rb and start the server like this:

$ rackup -r kawaii hello.rb --port 8088

Then navigate to http://localhost:8088 to see the greeting.

Using rackup

To run the app you created in the “Getting started” section above using rackup, create the following hello.ru file:

require 'kawaii'
require_relative 'hello'

run Kawaii::SingletonApp

SingletonApp contains all routes defined at the file scope.

Defining routes

There are several methods you can use to build your routes, handle passed parameters and so on.

Supported HTTP methods

The basic way to add a route handler is to invoke a method corresponding to the given HTTP verb, e.g.:

post '/users' do
  # Some response
end

Here, the post method corresponds to the POST HTTP verb.

Here's a list of supported HTTP verbs:

Wildcard matching

Patterns in route definitions may contain wildcard characters * and ?.

For example get '/users/?' matches both /users/ and /users while get '/users/*' will match any path starting with '/users/' e.g. '/users/foo/bar'.

Parameters

Route patterns may contain named parameters, prefixed with a colon. Parameters are accessible through the params hash in handler:

get '/users/:id' do
  params[:id]
end

(When requested with /users/123, the above route handler will render "123".)

Regular expressions

Route patterns may contain regular expressions. Example:

get %r{/users/.*} do
  'Hello, world'
end

Nested routes

Routes may be nested using the context method. Example:

context '/api' do
  get '/users' do
    'Hello'
  end
end

Will above handler will be accessible through /api/users.

Custom matchers

If string patterns and regular expression are not flexible enough, you can create a custom matcher.

A matcher instance responds to match method and returns either a Match instance or nil if there's no match. See documentation for Kawaii::Matcher#match for more details.

Request object

Handlers can access the Rack::Request instance corresponding to the current request:

get '/' do
  request.host
end

View templates

View templates must currently be stored in views/ directory of the project using Kawaii. They can be rendered using the render method:

get '/' do
  render('index.html.erb')
end

You can set instance variables and use them in the templates.

get '/' do
  @title = 'Hello, world'
  render('index.html.erb')
end

Let's say views/index.html.erb looks like this:

<h1><%= @title %></h1>

In that case, when you visit the page, you'll see Hello, world.

Supported templating engines include: ERB, Haml, Liquid, Builder, Kramdown and others. Note that you may need to include the specific gem implementing the given templating engine as inferred from the file name of the template.

Modular apps

For building more complex applications, you can split them into separate classes, each implementing a subset of functionality (e.g. website and an API).

To create an application, inherit from Kawaii::Base and define your routes inside the class.

Let's create website.rb:

require 'kawaii'

class Website < Kawaii::Base
  get '/' do
    'Hello, world'
  end
end

Now here's how api.rb may look like:

require 'kawaii'

class API < Kawaii::Base
  get '/info' do
    'This is some information'
  end
end

Let's use the apps in a config.ru:

require 'kawaii'
require_relative 'website'
require_relative 'api'

map '/' do
  run Website
end

map '/api' do
  run API
end

Model-view-controller apps

Kawaii supports routing to controllers by either specifying the specific controller + action for a given route or by creating automatic Restful resources (via route).

Let's suppose we have a controller in hello_world.rb has typical CRUD methods that mimick Rails controllers:

class HelloWorld < Kawaii::Controller
  def index
    'Hello, world'
  end
end

An in users.rb:

class Users < Kawaii::Controller
  def index
    'GET /users'
  end

  def show
    "GET /users/#{params[:id]}"
  end

  def create
    'POST /users'
  end

  def update
    "PATCH /users/#{params[:id]}"
  end

  def destroy
    "DELETE /users/#{params[:id]}"
  end
end

Here's how we can define routes (in app.rb):

require 'kawaii'
  require_relative 'hello_world'
  require_relative 'users'

  get '/', 'hello_world#index' # Explicitly route to `HelloWorld#index` to show the welcome page

  route '/users', 'users'

You can run the app directly using ruby or create config.ru:

require_relative 'app.rb'

run Kawaii::SingletonApp

Of course, you can

Testing

I recommend using Rack::Test for testing (see here). Look at specs in spec/ to see how you can use it.

To make a long story short, a class deriving from Kawaii::Base containing your routes is app. Let's suppose, your app class is MyApp, here's how you could test it:

describe MyApp
  let(:app) { MyApp }
  it 'renders home page' do
    get '/'
    expect(last_response).to be_ok
  end
end

Resources

See /examples

Reference

Contributing

Bug reports and pull requests are welcome on GitHub at github.com/bilus/kawaii.

License

The gem is available as open source under the terms of the MIT License.

TODO

Known issues

* There are many missing features and glitches are inevitable. The library hasn't been used in production yet. Please report them to gyamtso at gmail dot com. *

Rubocop

lib/kawaii/routing_methods.rb:46:1: C: Extra blank line detected.

The extra line is necessary for Yard to ignore the comment. Adjust Rubocop settings.