User:Hongyi23/sandbox

From Wikipedia, the free encyclopedia
Rack
Original author(s)Christian Neukirchen
Stable release
1.6.4 / June 18, 2015 (2015-06-18)
Operating systemCross-platform
LicenseMIT License
Websiterack.github.io

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 provides 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 TARGET
  • Rack::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]

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 lets do task one
end

task :task2 do
    puts lets do task two
end

task :final task => [:task1, :task2] do
    puts lets 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 lets 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 lets 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 lets 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 thats 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 tasks in 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]

References[edit]

  1. ^ "Rack API".
  2. ^ "Christian Neukirchen`s blog about Rack".
  3. ^ "PEP 333, Python Web Server Gateway Interface v1.0".
  4. ^ "Rack README".
  5. ^ "Ruby on Rails API".
  6. ^ "Rails on Rack Guide".
  7. ^ Seifer, Jason. "Rack tutorial".
  8. ^ Vroom, Ariejan. "Rake with namespaces and default tasks".
  9. ^ Grimm, Avdi. "Rake: Pathmap".