[Ruby ORM] Integrate Sequel to Ruby on Rails
Bài đăng này đã không được cập nhật trong 3 năm
Without any doubt, Ruby on Rails's still the hotest open source framework for web development. However, it doesn't mean RoR's perfect girl that all of guys wanna to date with. TeachEmpower has done a benchmark about web framework performance then RoR's position was the bottom of table. As a Rails lover, I want to figure out why Rails speed's so slow and find out the solution for this dark side. After some days experienced with Sequel, I has found the light at the end of tunnel.
1. Sequel - ActiveRecord slayer
There're so many article pointed out that ActiveRecord
is one of reason contribute to poor performance of Rails. Someone has blamed it on ORM while other want to improve ActiveRercord
performance by some precious tips which you can understand after at least over 5 years with Rails. Why we don't use another light weight ORM
to replace ActiveRecord
? The answer is Sequel
, a rare project hasn't any issues yet on github (Good job, Sequel team!)
Different to ActiveRecord
, a monolithic gem, Sequel
is built based on modular architect when Core part contains just few needed functions and all others're kept in Extension/Plugins and used in necessary case. Because of this design, Sequel can run five time faster than Active record.
Besides, developer can increase flexibility by choosing suitable Sequel plugin or writing a separated module which can fit system's requirements. In this post instead of meantioning about the bright side of Sequel
which has portraied in many blog posts(e.g http://twin.github.io/ode-to-sequel/) and comments on Github, I want to minimize the gap between Sequel and Rails developers who're almost familiar with ActiveRecord
.
2. Intergrate Sequel to RoR
2.1 Basic setup
2.1.1 Clear away ActiveRecord
The first thing to do before bring Sequel
to your life is elimiating everything of ActiveRecord
. If you start a new project, let add -O
or --skip-active-record
params to your rails new
command. If you want to get rid of ActiveRecord
in existing project, let follow this:
- In config/application.rb, remove
require rails/all
and add these line:
require "action_controller/railtie"
require "action_mailer/railtie"
require "sprockets/railtie"
require "rails/test_unit/railtie"
- In config/application.rb, remove
config.active_record.raise_in_transactional_callbacks = true
- In config/environments/development.rb, remove
config.active_record.migration_error = :page_load
- In config/environments/production.rb, remove
config.active_record.dump_schema_after_migration = false
It's notable that we don't have to remove config/database.yml
and the next part will be shown the reason why we have to keep it.
2.1.2 Install Sequel
Basically, Sequel
is made for pure Ruby code so it doesn't fully support Rails stack as ActiveRecord
. This's meaning that we have to setup Database from the starting point, manual generating migration files and create various tasks to do for migrating new data.
To make a shortcut, TalentBox team has made a terrific gem named sequel-rails which aim to bring Sequel
close to ActiveRecord users. For installation, just add this line to Gemfile then bundle
gem 'sequel-rails'
To connect to database, a plus point for sequel-rails
when employing config/database.yml
and similary to ActiveRecord
we don't need to change anything in configuration. This is the sample configuration for mysql
development:
adapter: mysql2
pool: 5
timeout: 5000
database: sample_sequel
user: myuser
password: 'mypassword'
Before start geeking, let spend few minutes to do some stuff in config files to make Sequel
become your new home for development. These setting can be placed in config/application.rb
or config/environments/
when you want some specify some extra functions for each environment
- For schema:
# Allowed options: :sql, :ruby.
config.sequel.schema_format = :sql
# Whether to dump the schema after successful migrations.
# Defaults to false in production and test, true otherwise.
config.sequel.schema_dump = true
- Overriding database.yml: Sure, we can do that but I prefer to do it in yml files
config.sequel.max_connections = 16
- Database tasks: Most exciting part, by default
config.sequel.load_database_tasks = true
When this flag's true, we can run database task as same as `ActiveRecord` commands but I'd like to specific command with `:sequel`
config.sequel.load_database_tasks = :sequel
then instead of `rake db:migration`, I'll let all the world know that I'm using `Sequel` when type `rake sequel:migration`
- Logger: indispensibale plugin that'll show off how fast of
Sequel
config.sequel.logger = Logger.new($stdout)
- Default plugins: as mentioned above, the basic component of
Sequel
is plugin and definitely there're some plugins that you want to load by default. For example, we want to add timestamps into every model, so just push it into configuration
config.sequel.after_connect = proc do
Sequel::Model.plugin :timestamps, update_on_create: true
end
Ok, I think now we almost done and we can start to enjoy Sequel
2.2 Use Sequel
like ActiveRecord
2.2.1 Migration
It's undeniable that ActiceRecord
has provided a rich tasks working with rake
command so sequel-rails
gem has exploited this advantages of ActiveRecord. To print out all tasks that sequel-rails
provides, let use rake -T
or rake --tasks
. And here're all tasks specific for migration
rake db:create[env] # Create the database defined in config/database.yml for the current Rails.env
rake db:create:all # Create all the local databases defined in config/database.yml
rake db:drop[env] # Drop the database defined in config/database.yml for the current Rails.env
rake db:drop:all # Drops all the local databases defined in config/database.yml
rake db:force_close_open_connections[env] # Forcibly close any open connections to the current env database (PostgreSQL specific)
rake db:migrate # Migrate the database to the latest version
rake db:migrate:down # Runs the "down" for a given migration VERSION
rake db:migrate:redo # Rollbacks the database one migration and re migrate up
rake db:migrate:reset # Resets your database using your migrations for the current environment
rake db:migrate:up # Runs the "up" for a given migration VERSION
rake db:reset # Drops and recreates the database from db/schema.rb for the current environment and loads the seeds
rake db:rollback # Rollback the latest migration file or down to specified VERSION=x
rake db:schema:dump # Create a db/schema.rb file that can be portably used against any DB supported by Sequel
rake db:schema:load # Load a schema.rb file into the database
rake db:seed # Load the seed data from db/seeds.rb
rake db:setup # Create the database, load the schema, and initialize with the seed data
rake db:structure:dump[env] # Dump the database structure to db/structure.sql
rake db:test:prepare # Prepare test database (ensure all migrations ran, drop and re-create database then load schema)
As we can see, it's bacsically same as ActiveRecord tasks so we don't need to change the habit when working with migration.
About migration files, when entering rails generate migration create_users
, a new migration file's created follow timestamps format which's similar to ActiveRecord. Now let dig into content of migration files
Sequel.migration do
change do
create_table :users do
primary_key :id
String :name
DateTime :created_at
DateTime :updated_at
end
end
end
There're some different points when working Sequel
migration:
primary_key
andforegin_key
: Ifid
of record is implicit in ActiveRecord, Sequel requires to define byprimary_key
. However, the appearance offoregin_key
help us to easily define the relation with other tables. E.g: when an user has many posts
Sequel.migration do
change do
create_table :posts do
primary_key :id
foreign_key :user_id, :users, index: true
String :content, text: true
DateTime :created_at
DateTime :updated_at
end
end
end
index
: Just adding the paramsindex: true
in the column- Timestamps: for
created_at
andupdated_at
columns, we need to place it into record and enable plugin:timestamps
inside Model - Data types: let a glance at this migration file
Sequel.migraion do
change do
create_table(:columns_types) do
Integer :a0 # integer
String :a1 # varchar(255)
String :a2, :size=>50 # varchar(50)
String :a3, :fixed=>true # char(255)
String :a4, :fixed=>true, :size=>50 # char(50)
String :a5, :text=>true # text
File :b # blob
Fixnum :c # integer
Bignum :d # bigint
Float :e # double precision
BigDecimal :f # numeric
BigDecimal :f2, :size=>10 # numeric(10)
BigDecimal :f3, :size=>[10, 2] # numeric(10, 2)
Date :g # date
DateTime :h # timestamp
Time :i # timestamp
Time :i2, :only_time=>true # time
Numeric :j # numeric
TrueClass :k # boolean
FalseClass :l # boolean
end
end
end
What I love in Sequel migration's simple, functional but still comprehensive. Same datatype is wrap into same group, if we want large space for them, just specify in optional fields. That's why we don't need `Text` type because it's almost same with `String` except size (lol). Besisdes, with `TrueClass` and `FalseClass`, we can forget about `Boolean, default: true/false`. So interesting!
2.2.2 Model
I think this part we can refer from document page of Sequel
because everything I write will be duplicated from Github page
3. The bottom line
Sometimes changing's deeply paintful, especially with something that belongs to soul but it's not imposible. Let take my posts as a reference for using Sequel
in Rails until it replaces completely ActiveRecord
in next versions of Ruby on Rails.
All rights reserved