Microframe is a lightweight portable ruby web framework modelled after Rails and inspired by Sinatra. It is an attempt to understand the awesome features of Rails by reimplementing something similar from scratch.
Just like Rails, Microframe is a full a MVC framework complete with it's own custom ORM. Also included are common utilities like generators, helpers and other niceties.
The prerequist for using Microframe is to have ruby installed. Microframe is developed using Ruby version 2.1.7 and as such will require a ruby setup for use.
With Ruby installed, you can install Microframe in one of two ways:
Add this line to your application's Gemfile:
gem 'microframe'And then execute:
$ bundle
Or install it yourself as:
$ gem install microframe
To create an app using Microframe
$ microframe new app_name
This will generate the correct files and folder structure required for a microframe app. Microframe tries to keep to the rails project structure:
Checkout Sample checklist app built entirely with Microframe.
Having bug issues?
- Check the sample app
- If not sampled: try it the Rails ways
- If not solved: check the list of outstanding features
- If not included, raise github issue
Microframe comes with a nice little ORM that closely mimicks Active Record. Currently, the ORM utilizes sqlite3 gem to implement support for the sqlite db.
Some of the missing AR semblance includes using migrations to manipulate the database. In it's place, models are expected to use the property keyword to define the nature of their db table.
For custom ORM with migration support check HanaRecord
property :id, type: :integer, primary_key: true
property :name, type: :text
create_tableThe snippet above represents a table with two columns
idandname. The id column is the primary_key of the table and is of typeinteger. The name column on the other hand is of typetext.
The property keyword instructs the ORM on the nature of the table to be created. The first argument is the name of the column in the db followed by the properties such as type, primary_key, nullable, auto_increment. These properties except type are expected to be either true or false.
The create_table keyword is very very important and must come after all the table properties have been defined. It triggers the actual creation of the table.
Routes follow the basic Rails routing pattern. It delivers the expected outcome and support for optional arguments and placeholders.
Sample
get "/lists/:list_id/items/:id/edit", to: "items#edit"
post "/lists/:list_id/items", to: "items#create"
patch "/lists/:list_id/items/:id", to: "items#update"
put "/lists/:list_id/items/:id", to: "items#update"
delete "/lists/:list_id/items/:id", to: "items#destroy"Microframe controllers follow Rails pattern both in naming and operation. Controllers must inherit from Microframe::Application. This makes the following methods available:
params, render, redirect, session, request.
Controller are expected to have a folder named after them in the view directory and within this directory you have view files for the various controller actions (except for those that end with a redirect)
Using Tilt gem, Microframe has support for erb files. Microframe implements the render method for views. Render expects two arguments, the view to be rendered and the view layout. If no layout is given, the default layout: application layout, is rendered. Likewise if no view is given, the default controller_named view is expected. Layouts are expected to be in the layout folder.
By default Microframe, not unlike Rails, assumes that the view to be rendered is a file named controller_action.html.erb located in a folder within the controller_named folder located in the views directory. If not found, it assumes the given path is the absolute path to the file.
If render is not called explicitly, implicitly, the default view and layout will be called.
The following resources, all controller instances variables, params (if available), are accessible in the views.
Check Sample checklist app for examples
Microframe supports using redirect if a render is not needed. The redirect method expects the full web address to redirect to. While sessions, flash, and notice are still in the works, important data can be passed to the new target as params.
Microframe supports rendering partials. This allows common view codes (such as form) to be abstracted to a single file which can be reused within the needed views. Find examples in the Sample checklist app.
Partials also have access to view resources.
The following helpers are available and (pretty much) retain their functionality as seen in Rails;
link_toimage_tagjavascript_tagstylesheet_tag
form_for helper is also available. form_for takes two arguments and a block. Within the block, the following methods are available: label, textarea, text_field, checkbox, hidden, submit
Currently, the form opening tag is instantiated with the first call to a form method. As such, HTML complications might arise if this first call is wrapped in html tags such as div, span etc. For the first call pass the desired html tag as part of the argument to the first form method called.
Microframe models should inherit from Microframe::ORM::Base. This gives them access to essential methods such as property, create_table, and other db related processes.
Each model have a table named after it in the database.
Microframe ORM strive to implement AR query style. So you can expect User.all to return all the users in the users table. Available query methods are:
all, select, find, find_by, where, count, first, last, limit, order, destroy
It also supports methods chaining; queries like User.first.name yields the expected result the name of the first user entry in the users table
In order to accurately support
method chaining, some trigger methods are required by certain methods to execute the chained queries. Queries are only executed when any of these triggers are included in the chain. These triggers are:
allfirstlastfindfind_by
All these methods, internally, use a
fetchmethod to trigger the execution of the query. Thefetchmethod can be called implicitly for queries that doesn't end with any of the methods.
User.all #=> SELECT * FROM users
User.count #=> User.all.size
User.first #=> SELECT * FROM users LIMIT 1
User.select("name, email").fetch #=> SELECT name, email FROM users
User.select("email").where("id > 10").select("name").limit("5").order("name DESC") #=> SELECT email, name FROM users WHERE id > 10 ORDER BY name DESC LIMIT 5
User.find_by(email: "[email protected]") #=> SELECT * FROM users WHERE email = '[email protected]'
User.select("name").find(11) #=> SELECT name FROM users WHERE id = 11
User.destroy(5) #=> DELETE FROM users WHERE id = 5Aside find, find_by, firstand last (which return individual data objects) and count (which returns an integer), every other query method returns a data collection which responds to normal collection methods such as each, includes?, map, etc
Updating model objects are also supported. Update can be done by using any of either the update or save method.
User.update(email: "[email protected]", name: "New name")This updates the given fields in the model and saves it.
Using the save method allows for the usual AR step by step update of an object's field(s). Note that save has to be called after making changes to an object's field.
User.name = "New name"
User.email = "[email protected]"
User.saveRails style validations is also available for models in Microframe. Validations get executed before a save or an update is performed. Note that the 'save' is implicitly called for 'create'. When a validation fails, the requested operation returns false. The errors inhibiting the operation can be accessed by calling the errors method on the object.
Example
validates :name, presence: true,
validates :name, length: { maximum: 50 },
validates :name, uniqueness: trueYou can also have multiple conditions in one line:
validates :name, presence: true, length: { maximum: 50 }, uniqueness: trueThe following are valid conditions
- presence
- absence
- length
- inclusion
- exclusion
- numericality
- uniqueness
- with
Sample
validates :username, exclusion: { in: %w(admin superuser) }
validates :age, inclusion: { in: 0..9 }
validates :age, inclusion: { within: 10..900 }
validates :first_name, length: { maximum: 30 }
validates :first_name, length: { minimum: 30 }
validates :first_name, length: { in: 30..35 }
validates :first_name, length: { is: 30 }
validates :age, numericality: { only_integer: true }
validates :age, numericality: { greater_than: true }
validates :age, numericality: { greater_than_or_equal_to: true }
validates :age, numericality: { less_than: true }
validates :age, numericality: { less_than_or_equal_to: true }
validates :username, presence: true
validates :username, absence: false
validates :username, uniqueness: trueYou can also validate with custom validators you define in the model by passing the name of the validator as value to with in the validates option:
validates :name, with: :custom_name_validator
def custom_name_validator
#some validation codes
#use error.add(err_message) to add an error message for failed validation
endYou can also use the validate_with keyword to define a custom validator. The validate_with accepts only one argument which is the method to be called during validation process
validate_with :my_validatorTo add error messages in a custom validator, use the add method on the error property of the object;
error.add("error message")Microframe supports has_many and belongs_to relation found in AR. And yes, they have similar behaviour.
property :id, type: :integer, primary_key: true
property :name, type: :text
create_table
has_many :itemsproperty :id, type: :integer, primary_key: true
property :description, type: :text
property :done, type: :boolean
property :list_id, type: :integer
create_table
belongs_to :listNote that the column for the foreign key must be included in the appropriate table. By default the foreign key, if not explicitly specified (as in the example above), is assumed to be [tablename]_id. Explicitly you can define the foreign_key as show below:
belongs_to :list, foreign_key: "list_id"Sample queries
List.first.items #=> Returns all the items belonging to the first list entry.
List.all.first.items.last.name #=> Returns the name of the last item belonging to the first list
Item.find_by(name: "Item name").list #=> Return the list to which the item with the name "Item name" belongs toThe burden of sanitizing (especially) user inputs lies on the developer. Microframe ORM security suite, like a couple of other features, it not robust enough. Plans to implement more security features is certainly on the Todo list. For now, I kindly indulge the developer to be awake to this responsibility.
Microframe uses the Thor gem to implement generators which makes for easy creation of core files required for a Microframe project.
Sample usage
$ microframe new [app_name] #=> Creates all the necessary directory for a new microframe app called app_name $ microframe generate model [model_name] column1_name:column1_type column2_name:column1_type #=> creates a model file named model_name within the model directory and defines the property for the given columns using the name and type $ microframe generate controller [controller_name] action1 action2 ... #=> creates a controller file named controller_name_controller.rb within the controller folder and defines the given action within it. It also create the views for the given action(s). $ microframe generate view [controller_name] view1 view2 #=> creates a folder for the given controller in the view directory with the given view files $ microframe server #=> Starts there rackup server. It can be called with optionals arguments to rackup
$ microframe sAfter checking out the repo, run bin/setup to install dependencies. Then, run rake test to run 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.
Bug reports and pull requests are welcome on GitHub at https://github.com/andela-ooranagwa/microframe. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
- Improve
sessionSecurity - Implement
cookies - Implement
flashmessages andnotice - Implement
nested resourcesin Routes - Implement
before actionfor controllers - Improve
routematchers - Implement
generating scaffold - Improve
microframe serverto acceptrackup arguments - Improve ORM security
- Implement modifying tables
- Implement support for more db types
The gem is available as open source under the terms of the MIT License.