This is a stripped down version of Rails and ActiveRecord. It utilizes Rack as web server interface. It takes http request through Rack::Request objects. It has its own router and routes that take http requests to appropriate controllers and render corresponding views. In order to use this piece of software, users will need to write controllers that inherit from ControllerBase class and write embedded ruby html files in the views folder. Controllers are responsible for constructing http responses while the ERB files are responsible for rendering the responses to viewers.
Just like ActiveRecord This web framework uses SQLite3 for its simplicity and lightweightness, the whole database is on a file. The setup for SQLite3 is quick, minimize headaches.
Begin initializing a SQL file, for example, the cats.sql
file. The SQLite3 ruby gem will take care of the rest.
In the DBConnection
class,
def self.open(db_file_name)
@db = SQLite3::Database.new(db_file_name)
@db.results_as_hash = true
@db.type_translation = true
@db
end
SQLite3 gem provides a very convenient way to initialize database. It also provides access to execute SQL queries.
The SQLObject class contains the core logic of object-relational mapping. For example, the well-known .all
, .find
, .create
, .save
ActiveRecord methods are implemented here.
def self.all
parameters = DBConnection.execute(<<-SQL)
SELECT *
FROM #{self.table_name}
SQL
parse_all(parameters)
end
The key self
refers to the object itself. Say I have a cats table, the relational mapped object here is Cat < SQLObject
. Cat
class will inherit these handy methods from SQLObject
class such that Cat.all
will return all cats in Ruby object format.
Associations are also implemented. has_many
and belongs_to
can be found in Associatable.rb
. Without going too much in depth, the association methods are simply SQL query on joining foreign_key
to primary_key
.
Every HTTP request will receive a response. The response is a HTML file. In the ControllerBase
class, render
and render_content
are responsible for delivering this final response. render
will construct an appropriate response from templates and instance variables while 'render_content' will write the result to HTML format and deliver it through Rack::Response
object.
Ruby has a ERB gem and it will parse erb file into raw HTML. However, one needs to bind the current context (local/instance variables) to the ERB template in order to get values of variables render in raw HTML
controller_name = self.class.to_s.underscore
template = ERB.new(
File.read("../views/#{controller_name}/#{template_name}.html.erb")
)
render_content(template.result(binding), "text/html")
Users will write custom controllers that inherit from ControllerBase
. ControllerBase
is there to provide the basic functionality on rendering a view. The key logic that made controller functional is the router. The router recognizes HTTP request methods such as POST
, GET
, DELETE
, and PATCH
. It channels the request to the appropriate controller. This is known as routing.
[:get, :post, :put, :delete].each do | http_method |
define_method(http_method.to_s) do | pattern, controller_class, action_name |
add_route(pattern, http_method, controller_class, action_name)
end
end
There are four routes. define_method
is a method that creates method, aka meta-programming.
These routes are customizable. Users will need to "draw" the routes so that router will recognize the intents of the web application
router = Router.new
router.draw do
get Regexp.new("^/cats$"), CatsController, :index
get Regexp.new("^/cats/new$"), CatsController, :new
get Regexp.new("^/cats/(?<id>\\d+)"), CatsController, :show
post Regexp.new("^/cats$"), CatsController, :create
end
An use case is illustrated in the example above: Users define get/post, the regular expression needed to match url pattern, and also the appropriate controller for the requests. Just like Rails!
- Flash cookie
- CSRF Protection