User:Muchen2015/Rack
Original author(s) | Christian Neukirchen |
---|---|
Stable release | 1.6.4
/ June 18, 2015 |
Operating system | Cross-platform |
License | MIT License |
Website | rack |
Rack is an abstraction layer and specification for interfaces between web servers and web frameworks for Ruby programming language. It provides a minimal, modular and adaptable API for construct web applications. Rack uses simple way, wrapping HTTP requests and responses, to combine web servers, web frameworks and web applications into a single method call[1]. The latest version of Rack is v1.6.4, published on June 18, 2015.
Origin
[edit]Rack is a standardized dominant interface in Ruby web development world, which was released by Christian Neukirchen in 2007[2]. The aim of Rack is to meet the demand of mix-and-match web servers and web applications, and to provide unified interface for web frameworks developer. Just like Unix pipes, to make it easy to mix and match web framework elements. Before that, there were many other methods to support Ruby and Ruby frameworks on server. CGI was first widely used method of running Ruby scripts on web server. Apache and FastCGI were most commonly methods of deploying Rails applications.
Specification overview
[edit]Rack has two sides: the web server side and web application side. Web server side refer to server or gateway, it provide an API to connect web servers and executes the application and a call function to the application side with environment information, which must be an instance of Hash that includes CGI-like headers[3]. The application side process the HTTP request and return a response to call function which contain an array of status, headers and a body. There may be a Rack middleware between the server side and the application side. For example:
Rack::Debugger
# Without argument runs first TARGETRack::URLMap
# Route to multiple applications inside the same process.Rack::CommonLogger
# Create Apache-style logfiles.Rack::File
# Serve static files.
Web frameworks with Rack support:[4]
- Camping
- Coset
- espresso
- Halcyon
- Mack
- Maveric
- Merb
- Racktools::SimpleApplication
- Ramaze
- Ruby on Rails
- Rum
- Sinatra (software)
- Sin
- Vintage
- Waves
- Wee
Receive request from a HTTP client, the server invokes the web application, then send to the application. Currently wrappers are available for WEBrick, FCGI, CGI, SCGI, Thin.
A Gem of Rack is available at rubygems.org. You can install it with:[5]
gem install rack
Rack middleware
[edit]A way to filter a request and response coming into the web application, and it implements the pipeline design pattern using Rack. The principle of the Rack middleware is to separately dispatch the HTTP requests, handle the sessions and parse the parameters. The server forwards a request to the middleware. The middleware processes the request and sends a request to another web application whose response is forwarded to the client[6]. It is common that there are multiple middleware components as a stack. Large sum of middleware components exist in the Rack library.
Basic functions
[edit]Specify directory
[edit]Build tools are very relevant with dependencies: files or file directories depend on each other to get complied and linked before moving on to next tasks[7]. Things are the same in rake files, dependencies should be specified before working on tasks. Simply use directory
to clarify directories in rake files.
directory “tmp”
file “hello_word.tmp” => “tmp” do
sh “echo ‘Hello Word’ > ‘tmp/hello_word.tmp’”
end
The task aims at output a string Hello Word
to the file whose directory is tmp/hello_word.tmp
. When the rake file is run, a directory named tmp
is created first before output the string.
Tasks
[edit]Clarify tasks
[edit]Multiple tasks can be defined in a rake file, and tasks can depend on other tasks. task
is used to defined tasks in a rake file.
task :task1 do
puts “let’s do task one”
end
task :task2 do
puts “let’s do task two”
end
task :final task => [:task1, :task2] do
puts “let’s do final task”
end
The code above defines three tasks using task
: task1, task2, and final task. When run the rake file, these tasks would be handled in order. Notice that the task1 and task2 are all prerequisites of the final task.
Default tasks
[edit]Also, default task can be defined in a rake file using :default
. A default task will be run if you type rake without any other arguments. The code above is modified and the task1 is set to be the default task.
task :default => :task1
task :task1 do
puts “let’s do task one”
end
...
Task description
[edit]Task description, which acts like annotation, can be added to tasks as a reminder. A task description can be defined using desc
.
desc “This is task one”
task :task1 do
puts “let’s do task one”
end
...
When the rake file is run with argument –T
, the output will be like the following:
$ rake task1 –T
rake This is task one
...
Redefine tasks
[edit]More things can be added on to an existing task. In the example below, more details are expected to be output within task one, so a task with the same name would be created. Within the new task1
, more items can be added.
task :task1 do
puts “let’s do task one”
end
task :task1 do
puts “the deadline for task one is tomorrow”
end
here is the result when this rake file is run:
$ rake task1
let’s do task one
the deadline for task one is tomorrow
Namespace
[edit]Namespace is supported in rake so that it is easy to group together similar tasks inside of one namespace[8].
namespace :tasks_for_today do
task :task1
...
When a task within a namespace is called, the namespace should be specified.
$ rake tasks_for_today:task1
let’s do task one
the deadline for task one is tomorrow
Invoking tasks
[edit]Rake allows to invoke a task from inside another task. In the following example, task one is invoked within the task task_schedule
.
namespace: tasks_for_today do
task :task_schedule do
Rake::Task[‘tasks_for_today:task1’].invoke
Puts “that’s our schedule for this morning”
end
end
...
which outputs:
$ rake tasks_for_today:task_schedule
let’s do task one
the deadline for task one is tomorrow
that’s our schedule for this morning
Advanced functions
[edit]File management
[edit]File list
[edit]Rake::FileList
is a powerful tool for file management. In the following example, files of the same extension are found and filtered.
This is the tree of the directory:
$ tree
├── ~file.txt
├── file1.txt
├── file2.txt
├── file3.txt
├── file4.doc
├── folder1
│ └── file_management.txt
├── folder2
│ └── appendix.txt
└── temp.txt
The goal is to read all the txt and doc file from the directory. The rake file could be edited as the following:
require 'rake'
Dir.chdir "files"
files = Rake::FileList["*.txt", "*.doc"]
which outputs:
files #=> ["~file.txt", "file1.txt", "file2.txt", "file3.txt", "file4.doc", "temp.txt"]
To add the left two txt files in folder1 and folder2, as well as filter the file start with ~
, the rake file can be modified as:
...
files = Rake::FileList["**/*.txt", "**/*.doc"]
files.exclude("~*")
the correct output will be shown:
files #=> ["file1.txt", "file2.txt", "file3.txt", "file4.doc", "file_management.txt", "appendix.txt", "temp.txt"]
Path map
[edit]In file management, it's crucial to provide correct filenames and the relative information, such as extension, and path. Pathmap takes as its argument a specification, which is a string containing codes corresponding to different parts of the original filenames[9].
%p: the whole original path. %f: filename without any directory portion. %n: base file name without extension or directory portions. %d: directory without file name %x: yields only the file extensions.
require './source_files'
SOURCE_FILES.pathmap("%p")
# => ["file1.txt", "file2.txt", "file3.txt", "file4.doc", "folder1/file_management.txt", "folder2/appendix.txt", "temp.txt"]
SOURCE_FILES.pathmap("%f")
# => ["file1.txt", "file2.txt", "file3.txt", "file4.doc", "file_management.txt", "appendix.txt", "temp.txt"]
SOURCE_FILES.pathmap("%n")
# => ["file1", "file2", "file3", "file4", "file_management", "appendix", "temp"]
SOURCE_FILES.pathmap("%d")
# => [".", ".", ".", ".", "folder1", "folder2", "."]
SOURCE_FILES.pathmap("%x")
# => [".txt", ".txt", ".txt", ".doc", ".txt", ".txt", ".txt"]
Add tasks to rails project
[edit]There might already be some tasksin a given rails project, and they can be run: rake --tasks
.
If more tasks are needed to be added or refined, a rake file which contains new tasks should be put into /lib/tasks
. The rake file will automatically detacted and add to the rails tasks list. The following example is a new task aim to create three new folders defined in a rake file named new.rake
.
namespace :new_tasks
desc "Create blank directories if they don't already exist"
task(:create_directories) do
shared_folders = ["folder1","folder2","folder3"]
for folder in shared_folders
if File.exists?("#{RAILS_ROOT}/public/#{folder}")
puts "#{RAILS_ROOT}/public/#{folder}exists"
Dir.mkdir "#{RAILS_ROOT}/public/#{folder}"
end
end
end
end
the new task will be added to task list when run rake --tasks
.
#tasks which are already in task list
rake tmp:pids:clear #Clear all files in tmp/pids
rake tmp:sessions:clear #Clear all files in tmp/sessions
rake tmp:sockets:clear #Clears all files in tmp/sockets
#the added task
rake new:new_tasks #Create blank directories if they don't already exist
See also
[edit]- PSGI – Perl Web Server Gateway Interface
- SCGI – Simple Common Gateway Interface
- WSGI – Python Web Server Gateway Interface
- JSGI – JavaScript web server gateway interface
- Make
- List of build automation software
References
[edit]- ^ "Rack API".
- ^ "Christian Neukirchen`s blog about Rack".
- ^ "PEP 333, Python Web Server Gateway Interface v1.0".
- ^ "Rack README".
- ^ "Ruby on Rails API".
- ^ "Rails on Rack Guide".
- ^ Seifer, Jason. "Rack tutorial".
- ^ Vroom, Ariejan. "Rake with namespaces and default tasks".
- ^ Grimm, Avdi. "Rake: Pathmap".