+3

Bắt đầu với Sinatra

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.

alt text

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

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

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

$ gem ruby dk.rb init
$ 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

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

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 :

Đọ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

http://bundler.io/

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

alt text

Ấ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

https://github.com/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' <[email protected]>",
    "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

http://log4r.rubyforge.org/

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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí