Shinkansen is a Ruby MVC web framework inspired by Ruby on Rails. The framework's key components are:
Router
: basic routing to Shinkansen controllersControllerBase
: controller actions, including view renderingModelBase
: basic Object-Relational Mapping (ORM) functionality
Add routes for the following CRUD actions: GET
, POST
, PUT
,
and DELETE
.
router.draw do
get Regexp.new("^/$"), MessagesController, :index
get Regexp.new("^/messages$"), MessagesController, :index
post Regexp.new("^/messages$"), MessagesController, :create
get Regexp.new("^/messages/new$"), MessagesController, :new
get Regexp.new("^/messages/(?<message_id>\\d+)$"), MessagesController, :show
delete Regexp.new("^/messages/(?<message_id>\\d+)$"), MessagesController, :destroy
end
#get
,#post
,#put
,#delete
- Define a route that matches the methodGET
,POST
,PUT
, orDELETE
. Takes(pattern, controller_class, action_name)
as arguments:pattern
- RegEx pattern to match routecontroller_class
- Controller class to instantiate for matched routeaction_name
- Controller action to execute
#draw {|| block}
- Include route definitions in the given block to add routes to the router#run(req, res)
- Run the router within a Rack applicationreq
- RackRequest
instanceres
- RackResponse
instance
Add Shinkansen model functionality by inheriting from the ModelBase
class. Call finalize!
within the model definition to add getters and
setters corresponding to database column names.
class Message < ModelBase
finalize!
end
Shinkansen utilizes Ruby metaprogramming methods to add methods to
ModelBase
classes. For example, finalize!
utilizes define_method
to add getter and setter methods corresponding to database columns.
def self.finalize!
columns.each do |column|
define_method(column) { attributes[column] }
define_method("#{column}=") { |value| attributes[column] = value }
end
end
Add the filenames of your SQLite database and setup file to
db/setup.rb
. Require setup.rb
in each of your models.
::finalize!
- Creates getter and setter methods for each database column::columns
- Returns an array of symbols representing database column names in the database#attributes
- Returns a hash of attributes mapped to attribute values#insert
- Adds the class instance to the database#update
- Updates the database row to match attribute values of the class instance#save
- Inserts or updates the class instance depending on whether or not itsid
isnil
#destroy
- Deletes the object's database entry
::all
- Returns an array of all instances of the class in the database::first
/::last
- Returns the first/last instance of the class in the database::find(id)
- Searches the database for an entry with the given id returning the matching class instance or nil, if it doesn't exist::where(params)
- Returns an array of class instances that match the conditions set inparams
, a hash that maps attributes to match values
#belongs_to(name, options)
- Creates a one-to-one association with another class. Takes an associationname
andoptions
hash, which specifies the following::class_name
- Name of the class that the association points to:foreign_key
- Name of the foreign key within this class:primary_key
- Name of the primary key within the associated class
#has_many(name, options)
- Creates a one-to-many association with another model. Also, takes an associationname
andoptions
hash, which specifies the following::class_name
- Name of the class that the association points to:foreign_key
- Name of the foreign key within the associated class:primary_key
- Name of the primary key within this class
#has_one_through(name, through_name, source_name)
- Creates a one-to-one association by going through a third class.name
- Name of the associationthrough_name
- Name of the association defined in this class to find the endpoint associationsource_name
- Name of the endpoint association
Add Shinkansen controller functionality by inheriting from the
ControllerBase
class.
class MessagesController < ControllerBase
# Controller actions...
end
Shinkansen controllers take advantage of the Rack::Request
and
Rack::Response
APIs to easily build responses. For example,
Shinkansen reads and writes session cookies using
Rack::Request#cookies
and Rack::Response#set_cookie
under the
_shinkansen_app
key.
class Session
attr_reader :session
def initialize(req)
cookie = req.cookies['_shinkansen_app']
@session = cookie ? JSON.parse(cookie) : {}
@session[:path] = '/'
end
def store_session(res)
cookie = session.to_json
res.set_cookie('_shinkansen_app', cookie)
end
# ...
end
#redirect_to(url)
- Builds 302 response that redirects to the givenurl
#render_content(content, content_type)
- Builds a response with the givencontent
andcontent_type
#render(template_name)
- Builds atext/html
response with the specified ERBtemplate_name
#session[]
/#session[]=
- Access/set data within a session cookie#flash[]
/#flash[]=
- Access/set data within a cookie that's cleared with every request#flash.now[]/#flash.now[]=
- Access/set data within a cookies that's only available for the current request
Shinkansen contains middleware to render a useful exceptions view upon
internal server error. To use, add ShowExceptions
to your Rack app
with Rack::Builder
.
app = Rack::Builder.new do
use ShowExceptions
run app
end.to_app
- Download or clone this repository.
bundle install
cd shinkansen/app
ruby message_board.rb
- Navigate to
localhost:3000
- Static assets middleware
- CSRF Protection
-
has_many_through
association - DB connection for PostgreSQL
- Gemify the library
- Database migrations