Bắt đầu với Sinatra
Bài đăng này đã không được cập nhật trong 7 năm
Vì cuộc đời là những chuyến đi, đọc là để cảm nhận, code là để trải nghiệm, vậy nên : Cứ đọc rồi sẽ hiểu, cứ code rồi sẽ biết Nếu đã đọc và code rồi nhưng không hiểu thì bỏ qua
Việc gì khó thì bỏ
Sinatra là gì?
Đây là những gì mà trên trang chủ Sinatra đã viết: "Sinatra là một DSL để xây dựng ứng dụng web bằng Ruby nhanh nhất với nỗ lực tối thiểu"
Vậy cụ thể là như thế nào, DSL (Domain-specific language) là một ngôn ngữ được thiết kế để thực hiện trong một lĩnh vực cụ thể, nó trái ngược với các ngôn ngữ có mục đích chung để giải quyết nhiều lĩnh vực. Sinatra là một thư viện Ruby có trọng lượng nhẹ để tạo ra các truy cập HTTP cực kì dễ dàng. Ruby đơn giản nhưng là một ngôn ngữ lập trình hướng đối tượng rất mạnh mẽ, cú pháp Ruby trong sáng và linh hoạt. Còn HTTP là một giao thức cực mạnh của ứng dụng Web.
HTTP (Hypertext Transfer Protocol) là một giao thức truyền tải, nó sẽ chấp nhận sự liên lạc giữa clients (người dùng) và servers (máy chủ) qua internet. Một client (như trình duyệt web) sẽ yêu cầu cung cấp tài nguyên (thông thường là nội dung một trang web) từ một server, server sẽ xử lý yêu cầu và sau đó sẽ gửi trả lại một phản hồi cho client. Phản hồi này sẽ chứa một mã trạng thái (thông thường là 200, chỉ ra rằng mọi thứ đều ổn) những yêu cầu và phản hồi này là những tin nhắn được gửi qua HTTP.
Sinatra làm những điều đó rất dễ dàng - gần như là bình thường - để xây dựng dịch vụ hay ứng dụng web bằng Ruby. Một ứng dụng Sinatra cơ bản được tạo bởi một hoặc nhiều tập tin Ruby. Bạn không cần thiết phải trở thành một chuyên gia Ruby để sử dụng Sinatra, nhưng nếu bạn biết sâu Ruby hơn, bạn sẽ tạo được các ứng dụng Sinatra một cách tốt nhất. Và bên cạnh đó, thật đáng tiếc nếu không học Ruby bởi vì nó là một ngôn ngữ rất thú vị. Mặt khác, học Sinatra và nghiên cứu những đoạn mã của người khác viết chắc chắn sẽ cải thiện kỹ năng lập trình Ruby của bạn. Như tôi đã đề cập ở trước, Sinatra là một thư viện có trọng lượng nhẹ, với dưới 2000 dòng mã viết bằng Ruby. Đó là một giá trị đáng để học tập, bạn sẽ biết Sinatra hoạt động như thế nào, và bạn cũng sẽ biết thêm nhiều đoạn mã Ruby rất tuyệt.
Sinatra được viết vào năm 2007 bởi Blake Mizerany, và liên tục được phát triển, tại thời điểm bài viết này thì Sinatra đã được tải hơn 25 triệu lần tại trang web RubyGems từ năm 2010. Cơ bàn thì vì sự yêu thích, nhưng Sinatra cũng có khả năng sáng tạo ra những web có dữ liệu lớn như BBC, Github, Linkedin. Và còn là ý tưởng cho các ngôn ngữ khác sao chép, kể ra như Express, Slim, Flasl, Spark và Nancy.
Không giống như Ruby on Rails, Sinatra được xác định không như một framework. Nó không có các quy ước và các áp đặt khung sườn tập tin cho bạn. Sinatra cơ bản là một ứng dụng Ruby, những gì Sinatra làm là kết nối ứng dụng đó vào Web (qua HTTP). Thay vì ẩn dấu phía sau nhiều ma thuật, thì Sinatra lại phơi bày cách mà một Web hoạt động bằng khái niệm của HTTP và URL. Điều đó có nghĩa là bạn hoàn toàn có thể xây dựng một Web có dữ liệu lớn và mạnh mẽ bằng Sinatra. Nó sẽ hoạt động theo cách mà bạn muốn mà không bị các quy ước hạn chế như Rails. Tuy vậy, Sinatra cũng sẽ không ngăn cản bạn viết các mã tệ.
Sinatra được xây dựng từ trên nền Rack, nó là một giao diện cấp thấp tương tác giữa một HTTP server và một đối tượng Ruby. Các Ruby Framework như Rails, Ramaze, Rango, Camping và Halcyon cũng được xây trên nền Rack. Nó giúp Sinatra dễ dàng mở rộng để sử dụng các API, RubyGem riêng cho ứng dụng của bạn.
Tại sao bạn nên sử dụng Sinatra ?
Sinatra giúp bạn viết những đoạn mã thanh lịch nhưng vẫn có kết quả tuyệt vời. Điều đó có nghĩa là bạn có thể tạo đầy đủ một ứng dụng web chỉ trong một tập tin. Nó không có các thủ tục thiết lập phức tạp hay phải lo lắng về cách cấu hình. Bạn chỉ cần mở một trình chỉnh sửa văn bản (sublime chẳng hạn) và bắt đầu, để bạn có thể tập trung vào ứng dụng của bạn.
Phát triển bằng Sinatra là hoàn hảo cho việc tạo mẫu các ý tưởng. Cú pháp của nó đủ để bạn bắt đầu, nhưng rất mạnh mẽ. Sinatra vô cùng linh hoạt - nó giải thoát cho bạn và giúp bạn làm những gì mà bạn muốn. Nó là lựa chọn hoàn hảo để triển khai API, Widgets, Facebook Apps và nhiều hơn nữa.
Và một điều cuối những không kém ý nghĩa, đó là cộng đồng hỗ trợ Sinatra khá tuyệt vời.
Mục lục
- Cài đặt Ruby
- Học Syntax
- Ruby API với Sinatra
- Làm bài tập: quản lý user
- Học và viết rspec cho bài tập
- Sử dụng một số Gem phổ biến trong ruby
Cài đặt Ruby
1. Cài đặt ruby, gem
Download Ruby bản 1.9.3
http://rubyinstaller.org/downloads/
Cài đặt thêm một số gem thường dùng
bundle (0.0.1) | json_serializer (0.1.0) |
bundler (1.10.6) | libv8 (3.16.14.11) |
coffee-script (2.4.1) | linecache19 (0.5.12) |
data_mapper(1.2.0) | mysql2 (0.3.19 x86-mingw32) |
database_cleaner (1.4.1) | pry (0.10.1 i386-mingw32) |
debugger (1.6.8) | pry-debugger (0.2.3) |
dm-core (1.2.1) | rack (1.6.4) |
dm-migrations (1.2.0) | rack-test (0.6.3) |
do_mysql (0.10.16 x86-mingw32) | rest-client (1.8.0 x86-mingw32) |
font-awesome-sass (4.3.2.1) | rspec (3.3.0) |
ruby-mysql (2.9.13) | json_pure (1.8.2) |
Cú pháp cài gem :
$ gem install ten_gem
- Trang chủ : https://rubygems.org
- Tham khảo thêm (liệt kê các gem phổ biến, theo chủ đề) : https://www.ruby-toolbox.com/
2. Cài DevKit ruby
-
Download DevKit từ http://rubyinstaller.org/downloads/ và giải nén vào 1 thư mục (ví dụ C:\DevKit Ruby)
-
Mở cmd ruby lên và cd tới thư mục vừa giải nén ở trên
-
Gõ
$ gem ruby dk.rb init
- Gõ
$ gem ruby dk.rb install
3. Chạy ứng dụng ruby
-
Chạy bằng Interactive Ruby : Gõ lệnh trực tiếp
-
Chạy qua các tool để dev : Sublime, Eclipse, ..
-
Chạy bằng cmd Ruby, dùng lệnh cd để chuyển đến thư mục làm việc, có 2 cách :
- Chạy file trực tiếp, cổng mặc định là 8080, gõ lệnh :
ruby [file_code_ruby.rb]
- Chạy qua rack, cổng mặc định là 9292, gõ lệnh:
rackup config.ru
. Nếu muốn sử dụng cổng khác (ví dụ 6969), dùng lệnh:thin -R config.ru -a 127.0.0.1 -p 6969 start
- Chạy file trực tiếp, cổng mặc định là 8080, gõ lệnh :
Học Syntax
Thao khảo các trang web sau :
Ruby API với Sinatra
Cài đặt
Cài đặt sinatra gem file:
$ gem install sinatra
Hello World nào
Đầu tiên bạn cần tạo file: app.rb
# app.rb
require 'sinatra'
class HelloWorldApp < Sinatra::Base
get '/' do
"Hello, world!"
end
end
Gõ ruby app.rb
trong ruby cmd để chạy .
Routes
Trong sinatra 1 route được định nghĩa với 1 method HTTP
get '/' do
.. show something ..
end
post '/' do
.. create something ..
end
put '/' do
.. replace something ..
end
patch '/' do
.. modify something ..
end
delete '/' do
.. annihilate something ..
end
options '/' do
.. appease something ..
end
link '/' do
.. affiliate something ..
end
unlink '/' do
.. separate something ..
end
Trong link cũng có thể bao gồm các parameters. Dữ liệu được lấy thông qua hash:params
.
get '/hello/:name' do
# Khi gọi link "GET /hello/foo" and "GET /hello/bar"
# params[:name] sẽ lấy được ra là 'foo' or 'bar'
"Hello #{params[:name]}!"
end
Chúng ta cũng có thể đặt tên cho param truy cập. như ví dụ trên ta sẽ gắn param name vào biến n.
get '/hello/:name' do |n|
# khi gọi link "GET /hello/foo" and "GET /hello/bar"
# params[:name] sẽ là 'foo' hoặc 'bar' và được lưu trong biến n
"Hello #{n}!"
end
Trong route ta cũng có thể sử dụng ký hiệu *, các giá trị được truyền vào * sẽ được lưu trong params[:splat]
kiểu array.
get '/say/*/to/*' do
# gọi link /say/hello/to/world
params[:splat] # = ["hello", "world"]
end
get '/download/*.*' do
# gọi link /download/path/to/file.xml
params[:splat] # = ["path/to/file", "xml"]
end
Cũng giống như trên ta có thể gắn các * vào các biến khác nhau.
get '/download/*.*' do |path, ext|
[path, ext] # = ["path/to/file", "xml"]
end
Ta cũng có thể sử dụng matching với Regular Expressions!.
get %r{/get/(\d\d)-(\d\d)-(\d\d\d\d)} do|month,day,year|
"Get requested from #{month}/#{day} in #{year}"
end
Làm bài tập: Quản lý User
Mục tiêu : Xây dựng 1 WebService sử dụng Sinatra để thực thi các lệnh như
update
,delete
,create
,... Kết quả trả về hiển thị ở phía trình duyệt của client
Yêu cầu hệ thống :
- MySQL Server 5.2.1
- Postman extention cho chrome dùng để test : Download
Tạo thư mục với cấu trúc như sau :
Sinatra_Service
|
+-models
| |
| +-user.rb
+-routers
| |
| +-routes.rb
| +-user.rb
Nội dung file :
#models/user.rb
require 'sequel'
require 'json'
Sequel.connect(:adapter=>'mysql2', :host=>'localhost', :database=>'sinatra', :user=>'root', :password=>'1234', :encoding=>'utf8')
class Sequel::Model
self.plugin :json_serializer
end
class User < Sequel::Model
unrestrict_primary_key
end
Trong đó :
- Đoạn này dùng để connect với data trong MySQL của chúng ta :
Sequel.connect(:adapter=>'mysql2', :host=>'localhost', :database=>'sinatra', :user=>'root', :password=>'1234', :encoding=>'utf8')
- Đoạn này phải có nếu muốn convert
params
truyền vào thành mảng
class Sequel::Model
self.plugin :json_serializer
end
#routers/user.rb
#$LOAD_PATH << '.'
require File.dirname(__FILE__) + '/../models/user.rb'
require 'sinatra/base'
class UsersServices < Sinatra::Base
before do
content_type :json, :charset => 'utf-8'
end
#-----------------
# Listing users
get '/users' do
#binding.pry
@users = User.all
if @users
p @users
@users.to_json
else
error 404, {:error => "database is empty"}.to_json
end
end
# Showing user
get '/user/:id' do
@user = User.find(:id => params[:id])
if @user
# p @user
if @user.id < 100
@user.to_json
else
error 400, {:error => "user id must be < 100"}.to_json
end
else
error 404, {:error => "user not found"}.to_json
end
end
# Edit user
put '/user/:id/update' do
jdata = JSON.parse(params.to_json,:symbolize_names => true)
@user = User.find(:id => params[:id])
if @user
begin
# if jdata.has_key?(:username)
# @user.username = params[:username]
# end
if jdata.has_key?(:password)
@user.password = params[:password]
end
if jdata.has_key?(:name)
@user.name = params[:name]
end
if jdata.has_key?(:address)
@user.address = params[:address]
end
if jdata.has_key?(:email)
@user.email = params[:email]
end
@user.save_changes
status 202
@user.to_json
rescue => e
error 400, {:error => e.message}.to_json
end
else
error 404, {:error => "user not found"}.to_json
end
# redirect to ("/user#{@user.id}")
# p @user
# @user.to_json
end
# Delete user
delete '/user/:id/delete' do
@user = User.find(:id => params[:id])
if @user
begin
if @user.id%2 == 0
@user.delete
status 202
{:success => "user has been deleted"}.to_json
else
error 400, {:error => "user id must be divisible 2"}.to_json
end
rescue => e
error 400, {:error => e.message}.to_json
end
else
error 404, {:error => "user not found"}. to_json
end
end
# Create new user
post '/user/new' do
jdata = JSON.parse(params.to_json,:symbolize_names => true)
begin
User.insert(User.load(
:username=>params[:username],
:password=>params[:password],
:name=>params[:name],
:address=>params[:address],
:email=>params[:email]
))
#, {:message => "user had been created"}.to_json
status 201
{:message => "user had been created"}.to_json
rescue => e
error 404, {:error => e.message}.to_json
end
end
end
- Đây là file router của chúng ta, lưu ý là
kết quả trả về (json) và status HTTP phải có ý nghĩa tương ứng
#routers/routes.rb
$LOAD_PATH << '.'
require 'user'
UsersServices.run!
- Khai báo
UsersServices.run!
để sủ dụng class router chúng ta đã tạo - Thực thi :
$ruby routes.rb
Học và viết rspec cho bài tập
RSpec là một framework test cho Ruby, viết RSpec có thể giúp chúng ta kiểm tra tính chính xác của chương trình chúng ta viết
Đọc tài liệu trước khi bắt đầu :
- http://vietonrails.com/201411-co-ban-ve-rspec-phan-1/
- http://rails-guides.rubygirls.org.vn/testing-rspec/
Đọc xong rồi thì tiếp tục đọc
Sinatra_Service
|
+-spec
| |
| +-spec_helper.rb
| +-user_spec.rb
+-models
| |
| +-user.rb
+-routers
| |
| +-routes.rb
| +-user.rb
Nội dung :
# spec/spec_helper.rb
# Load the Sinatra app
require File.dirname(__FILE__) + '/../routers/user'
require 'rspec'
require 'rack/test'
require 'sinatra'
set :environment, :test
RSpec.configure do |conf|
conf.include Rack::Test::Methods
end
def app
Sinatra::Application
end
- Khai báo
spec_helper.rb
ở một file sau đó gọi lại giúp chúng ta đỡ mất thời gian viết code và trông chương trình rõ ràng hơn
# spec/user_spec.rb
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe 'Routes service test' do
def app
UsersServices.new
end
before(:each) do
@params = {
id: 48,
username: 'newuser',
password: 'newpassword',
name: 'newname',
address: 'newaddress',
email: 'newemail'
}
@params_2 = {
id: 50,
username: 'newuser',
password: 'newpassword',
name: 'newname',
address: 'newaddress',
email: 'newemail'
}
@params_3 = {
# :id = 0,
username: 'newuser',
password: 'newpassword',
name: 'newname',
address: 'newaddress',
email: 'newemail'
}
end
# Listing users
it "should load list user and showing data" do
get "/users"
expect(last_response).to be_ok
end
# Showing user
it "should showing user" do
get "/user/#{@params[:id]}"
expect(last_response.status).to eq(200)
end
it "should showing user with id < 100" do
get "/user/200"
expect(last_response.status).to eq(200)
end
# Edit user
it "should update user" do
put "/user/#{@params[:id]}/update",{ "name" => @params[:name] }
expect(last_response.status).to eq(202)
get "/user/#{@params[:id]}"
user = JSON.parse(last_response.body)
expect(user['name']).to eq @params[:name]
end
# Delete user
it "should delete user" do
delete "/user/#{@params_2[:id]}/delete"
expect(last_response.status).to eq(202)
get "/user/#{@params_2[:id]}"
expect(last_response.status).to eq(404)
end
it "should delete user with user id divisible 2" do
delete "/user/119/delete"
expect(last_response.status).to eq(202)
get "/user/119"
expect(last_response.status).to eq(404)
end
# Create new user
it "should create new user" do
post "/user/new", {''=> @params_3}
expect(last_response.status).to eq(201)
user = JSON.parse(last_response.body)
expect(user['message']).to eq "user had been created"
end
end
- File
user_spec.rb
chứa các trường hợp test mà chúng ta nghĩ ra
AutoTest
Ngồi test bằng tay khá là mỏi, nên nhân loại mới nghĩ ra autotest
Đọc cái này đầu tiên : http://code.tutsplus.com/tutorials/how-to-integrate-rspec-into-a-sinatra-app--net-21564
Các gem gần thiết :
$ gem install ZenTest
$ gem install autotest-fsevent
$ gem install autotest-growl
Cây thư mục thêm một số file như sau :
Sinatra_Service
|
+-spec
| |
| +-spec_helper.rb
| +-user_spec.rb
+-models
| |
| +-user.rb
+-routers
| |
| +-routes.rb
| +-user.rb
+-.rspec(bắt buộc phải có, cho dù nội dung rỗng)
+-.autotest
Nội dung :
.rspec
--format documentation
--format documentation --color
- Khai báo format màu của text trong cmd ruby
.autotest
require 'autotest/fsevent'
require 'autotest/growl'
- Khai báo các gem cần thiết để sử dụng autotest
Chạy autotest
:
$ autotest
- Mỗi lần chúng ta sửa code, hệ thống lại tự động chạy lại
test
Sử dụng một số Gem phổ biến trong ruby
gem install thin
http://www.rubydoc.info/gems/thin/1.6.3
1. Thin Server là gì
Thin là một máy chủ web Ruby được gắn kết với nhau bởi 3 thư viện Ruby tốt nhất trong lịch sử web :
- Mongrel parser: 1 web-server tốc độ và bảo mật
- Event Machine: một mạng thư viện vào ra với khả năng mở rộng cao, hiệu suất tốt và ổn định
- Rack: một giao diện tối giản giữa máy chủ web và Ruby frameworks
Điều này làm cho Thin trở thành máy chủ web Ruby an toàn, ổn định, nhanh và có khả năng mở rộng, được gói gọn trong một gem có dễ dàng sử dụng.
2. Thin Server và 1 số Web server khác
2.1 Phusion Passenger
Ngày nay Phusion Passenger đã trở thành máy chủ được khuyến nghị cho Ruby on Rails. Passenger sở hữu tính năng phong phú, đáp ứng các nhu cầu cần thiết, đồng thời đơn giản hoá quá trình set up, khởi tạo thủ tục. Passenger loại bỏ kiến trúc với các máy chủ trung gian truyền thống, thay vào đó tích hợp trực tiếp trong Apache và Nginx.
Passenger cung cấp khả năng làm việc với nhiều ứng dụng được lưu trữ trên cùng một máy chủ.
Phiên bản mã nguồn mở của nó có một chế độ hoạt động đơn luồng đa tiến trình (multi-process single-threaded), trong khi phiên bản Enterprise có thể được cấu hình để làm việc, hoặc đơn luồng (single-threaded) hay đa luồng (multi-threaded).
Đối với người dùng doanh nghiệp, Passenger cung cấp một số tính năng thêm tiên tiến khác như: xử lí đồng thời và xử lý đa luồng, triển khai đồng loạt, kiểm soát và hạn chế tài nguyên ...
2.2 Puma
Puma là một máy chủ Ruby được thiết kế chuyên biệt dành cho Rack. Nó được lấy cảm hứng từ máy chủ web Mongrel, mà đã cách mạng hóa rất nhiều trong suốt thời gian nó đã được phát hành và bị ảnh hưởng như thế nào ứng dụng của Ruby đã phục vụ cho nhiều thế hệ (máy chủ) để đi. Nhà phát triển của Puma, Evan Phoenix, quyết định chuyển đổi cơ cấu hoạt động của Mongrel sang cơ cấu chỉ hoạt động trên Rack (và do đó loại bỏ sự phức tạp gây ra suy giảm hiệu suất) và thiết kế các ứng dụng để hỗ trợ xử lý song song thực sự, cho phép xử lí đồng thời.
Puma có một số chế độ làm việc: nó cho phép bạn thiết lập số lượng tối thiểu và tối đa luồng (thread) có thể sử dụng để làm việc của mình và cũng như cung cấp chế độ clustered nhờ đó mà bạn có thể sử dụng các quá trình fork process để xử lý yêu cầu đồng thời.
Puma không trực tiếp hỗ trợ host nhiều ứng dụng tuy nhiên nó lại có Jungle: một công cụ để giúp đáp ứng nhu cầu đa ứng dụng (multiple applications) của người dùng.
2.3 Unicorn
Unicorn là 1 máy chủ web rất phát triển của Ruby thậm chí tương thích cả với Python. Unicorn là 1 máy chủ web đầy đủ tính năng, tuy nhiên, nguyên tắc làm việc của nó là phủ nhận thiết kế cố gắng làm tất cả mọi thứ, chỉ làm những gì cần phải được thực hiện (bởi một máy chủ ứng dụng web) và ủy thác phần còn lại cho những bộ phận khác có thể làm tốt hơn nó.
Unicorn hỗ trợ khá nhiều các tính năng
Khả năng quản lí process: Unicorn có khả năng sinh, quản lí, khôi phục lại các worker bị chết. Khả năng cân bằng tải: Đảm bảo căn bằng tải, không bao giò để chất đống công việc lên 1 worker Khả năng nâng cấp mà không bị mất kết nối. Bạn có thể nâng cấp Unicorn, toàn bộ ứng dụng của bạn, thư viện của Ruby của bạn mà không phải ngắt kết nối. ...
2.4 So sánh với Thin Server
- Phusion Pasenger Dễ cấu hình, phổ biến, thích hợp để host nhiều ứng dụng (multiple application).
- Puma Không dựa vào EventMachine, thích hợp để chạy (single application)
- Unicorn: Nhiều tính năng hơn, hiệu năng cao tuy nhiên đòi hỏi cấu hình phức tạp.
- Thin: Dựa trên EventMachine, cấu hình đơn giản, thích hợp với (single application)
3. Cài đặt và sử dụng Thin Server
3.1 Cài đặt
Cài đặt phiên bản mới nhất
$ gem install thin
3.2 Sử dụng
Việc sử dụng Thin khá đơn giản. Trước hết, hãy đảm bảo bạn đã thêm 'thin' vào Gemfile Sau đó trên di chuyển đến thư mục của app và khởi động Thin
cd to/your/app
thin start
3.3 Cấu hình Thin Server
Bạn có thể thiết lập cấu hình của Thin Server trong file yalm (ví dụ config.yalm
) và sử dụng lệnh thin -C config.yml
để chạy Thin Server với cấu hình đã thiết lập trên.
Dưới đây là 1 mẫu config của Thin Server
---
user: www-data
group: www-data
pid: tmp/pids/thin.pid
timeout: 30
wait: 30
log: log/thin.log
max_conns: 1024
require: []
environment: production
max_persistent_conns: 512
servers: 1
threaded: true
no-epoll: true
daemonize: true
socket: tmp/sockets/thin.sock
chdir: /path/to/your/apps/root
tag: a-name-to-show-up-in-ps aux
gem install bundler
Cài đặt
$ gem install bundler
Sử dụng
Lợi ích đầu tiên của việc sử dụng bundle là giúp chúng ta giảm thời gian cài đặt thư viện. Giả sử chúng ta có 100 thư viện và phải gõ 100 lần $ gem install ...
, thì bây giờ chúng ta tạo 1 file Gemfile
và khai báo các thư viện cần thiết sau đó cài đặt gem bằng lệnh :
.
|
+-Gemfile
+-----------
+-------------
+----
+------
Nội dung Gemfile
(ví dụ)
gem "sinatra"
gem "tilt-jbuilder", ">= 0.4.0", :require => "sinatra/jbuilder"
gem "hashie"
gem "thin"
Gõ và mọi gem sẽ được cài
$ bundle install
Nâng cao về bundler đọc ở đây :
https://viblo.asia/obito/posts/z3NVRkJLv9xn
gem install debugger
http://www.rubydoc.info/gems/debugger/1.6.8
Cài đặt
$ gem install debugger
$ gem install pry-debugger
Sử dụng
Chúng ta có thể sử dụng debugger
tuy nhiên khuyến cáo là nên sử dụng pry-debugger
vì nó có màu dễ nhìn hơn
Tài liệu nên đọc trước :
Khai báo ở trong source để sử dụng pry-debugger
require 'pry-debugger'
Muốn debug đoạn nào thì chúng ta thêm binding.pry
vào đầu
Ví dụ :
# Listing users
get '/users' do
binding.pry
@users = User.all
if @users
p @users
@users.to_json
else
error 404, {:error => "database is empty"}.to_json
end
end
step : Nhảy từng dòng trong code, nếu gặp hàm thì nhảy vào trong hàm
next : Nhảy từng dòng trong code, nếu gặp hàm thì không nhảy vào trong hàm
finish : Bỏ qua debug và tiếp tục chạy
continue : Chạy chương trình và kết thúc session debug hiện tại
sinatra-authentication
https://github.com/maxjustus/sinatra-authentication
Cài đặt
Chạy source code trong thư mục sinatra-authentication
.
Sử dụng
Ở đây chúng ta tạo 1 trang web sử dụng sinatra với các phương thức login
, logout
module Authentication
def authenticate!
unless session[:user]
session[:original_request] = request.path_info
redirect '/signin'
end
end
end
get '/protected/?' do
authenticate!
erb :protected, locals: { title: 'Protected Page' }
end
get '/signin/?' do
erb :signin, locals: { title: 'Sign In' }
end
Ấn vào nút sign in sẽ gửi 1 request HTTP POST tới signin route
post '/signin/?' do
if user = User.authenticate(params)
session[:user] = user
redirect_to_original_request
else
flash[:notice] = 'You could not be signed in. Did you enter the correct username and password?'
redirect '/signin'
end
end
sinatra-contrib
https://github.com/sinatra/sinatra-contrib
Cài đặt
$ gem install sinatra-contrib
Sử dụng
Chứa các thành phần mở rộng của sinatra, nói một cách đơn giản là giống extensions, ở trong chương trình chúng ta thường xuyên sử dụng đến gem này
Một số gem hay sử dụng như sinatra/json
, sinatra/custom_logger
chẳng hạn
gem install rspec
Cài đặt
$ gem install rspec
Sử dụng
Dùng để test tính đúng sai của chương trình
gem install faker
https://github.com/stympy/faker
Cài đặt
$ gem install faker
Sử dụng
Giúp lập trình viên giảm thời tạo dữ liệu mẫu, áp dụng ở trong code của chúng ta :
# Create new user
post '/user/new_test' do
logger.info "Create new user_test"
begin
User.insert(User.load(
:username=>Faker::Internet.user_name,
:password=>Faker::Internet.password,
:name=>Faker::Name.name,
:address=>Faker::Address.street_address,
:email=>Faker::Internet.email
))
#, {:message => "user had been created"}.to_json
status 201
{:message => "user had been created"}.to_json
rescue => e
error 404, {:error => e.message}.to_json
end
end
end
gem install jbuilder
https://github.com/rails/jbuilder
Cài đặt
$ gem install jbuilder
Để sử dụng trên sinatra cần cài thêm gem : tilt-jbuilder
,hashie
gem install json
http://json-jruby.rubyforge.org/
Cài đặt
$ gem install json
Sử dụng
Cho phép định nghĩa 1 cấu trúc JSON bằng code và return ra json phía client
# app/views/message/show.json.jbuilder
json.content format_content(@message.content)
json.(@message, :created_at, :updated_at)
json.author do
json.name @message.creator.name.familiar
json.email_address @message.creator.email_address_with_name
json.url url_for(@message.creator, format: :json)
end
if current_user.admin?
json.visitors calculate_visitors(@message)
end
json.comments @message.comments, :content, :created_at
json.attachments @message.attachments do |attachment|
json.filename attachment.filename
json.url url_for(attachment)
end
Khi user nhận được
{
"content": "<p>This is <i>serious</i> monkey business</p>",
"created_at": "2011-10-29T20:45:28-05:00",
"updated_at": "2011-10-29T20:45:28-05:00",
"author": {
"name": "David H.",
"email_address": "'David Heinemeier Hansson' <david@heinemeierhansson.com>",
"url": "http://example.com/users/1-david.json"
},
"visitors": 15,
"comments": [
{ "content": "Hello everyone!", "created_at": "2011-10-29T20:45:28-05:00" },
{ "content": "To you my good sir!", "created_at": "2011-10-29T20:47:28-05:00" }
],
"attachments": [
{ "filename": "forecast.xls", "url": "http://example.com/downloads/forecast.xls" },
{ "filename": "presentation.pdf", "url": "http://example.com/downloads/presentation.pdf" }
]
}
gem install log4r
Cài đặt
$ gem install log4r
Sử dụng
Gem này giúp chúng ta dễ dàng lưu log vào 1 file trên server để sau này tiện cho việc tra cứu. Tuy nhiên ở trong sinatra thì không cần sử dụng gem này, sinatra đã hỗ trợ sẵn gem lưu log là custom_logger
có tính năng tương tự
........
require 'sinatra/custom_logger'
....
class UsersServices < Sinatra::Base
helpers Sinatra::CustomLogger
#development
configure :development do
...
logger = Logger.new(File.open("#{root}/log/#{environment}.log", 'a+'))
logger.level = Logger::DEBUG if development?
set :logger, logger
end
#----------------
....
# Listing users
get '/users' do
...
logger.info "Listing users"
...
end
.......
All rights reserved