S2CGI Web Framework is a small framework for creating the Ruby Application which is executed as a CGI script on Apache HTTPD Server.
Please export s2cgi from following svn repository.
As follows, a project directory will be created.
- https://www.seasar.org/svn/sandbox/s2container.ruby/trunk/s2cgi/
project/ config/ # configuration files are stored. lib/ # Service and Logic classes are stored. public/ # published to WEB. test/ # UnitTests are stroed. tpl/ # erb template files are stored. var/ # Data and Logs are stored. vendor/ # Dependent Libraries are stored.
Please install S2Container.Ruby following an install document.
Please install Rack, if you use it.
Extension cgi is registered as a cgi script.
And publish to WEB the public directory.AddHandler cgi-script .cgi Alias /s2cgi/ "/path/to/project/public/" <Directory "/path/to/project/public"> Options ExecCGI AllowOverride None Order allow,deny Allow from localhost </Directory>
Base URL should be set up appropriately. You can set Base URL in environment.rb file of a config directory.% cat config/environment.rb | grep BASE_URL BASE_URL = '/s2cgi' %Please check the owner and the right of execution of a cgi script of a public directory. Shebang of cgi script should be set up appropriately.% ls -l public/cgi/quick1.cgi -rwxr--r-- 1 apache apache 1250 Feb 1 00:00 public/cgi/quick1.cgi % head -1 public/cgi/quick1.cgi #!/usr/bin/env ruby %Please check the owner and the right of execution of var directory.% ls -ld var drwxr-xr-x 6 apache apache 4096 Feb 1 00:00 var %
Starting of CGI Framework will be done by calling Seasar::CGI.run method. As an example, let's create the following quick1.cgi in public/cgi directory.
% cat public/cgi/quick1.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/cgi.rb' Seasar::CGI.run %Next, the erb template file of quick1.cgi is created as quick1.html in a tpl/cgi directory.
% cat tpl/cgi/quick1.html Hello World %Please browse http://localhost/s2cgi/cgi/quick1.cgi, you can see "Hello World".
You can set the instance of Seasar::CGI::Page class as the argument of Seasar::CGI.run method. As an example, let's create the following quick2.cgi in public/cgi directory.
% cat public/cgi/quick2.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/cgi.rb' class Page < Seasar::CGI::Page; end Seasar::CGI.run(Page.new) %Next, the erb template file of quick2.cgi is created as quick2.html in a tpl/cgi directory.
% cat tpl/cgi/quick2.html Hello World 2 %Please browse http://localhost/s2cgi/cgi/quick2.cgi, you can see "Hello World 2".
Seasar::CGI.run method gets the component of Seasar::CGI::Page class from S2Container, when an argument is nil. When the component of Seasar::CGI::Page class does not exist in a container, the instance of Seasar::CGI::Page class is generated automatically.
Seasar::CGI::Page class generates contents from the erb template file of the tpl directory as default processing. As for the path to an erb template file, the path below BASE_URL of SCRIPT_NAME is used. As an example, when SCRIPT_NAME is "/s2cgi/cgi/quick2.cgi", and BASE_URL is "/s2cgi", then the path of an erb tenplate file will be "tpl/cgi/quick2.html".
In the case of getting Page component from S2Container, the CGI script is as follows.
% cat public/cgi/quick3.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/cgi.rb' class Page < Seasar::CGI::Page s2comp end Seasar::CGI.run %
The class variable of Seasar::CGI::Page class is shown below.
@@fatal.
It has a procedure object which will be called when an error occurs after framework has started. The caught error instance and the instance of Seasar::CGI::Page class are passed to a procedure object.
By the default, it is set up as follows within config/cgi.rb.
Seasar::CGI::Page.fatal {|e, page| s2logger.fatal() {"#{e.message} #{e.backtrace}"} print "Location: #{BASE_URL}fatal.html\n\n"; }
@@tpl_dir.
The path to the directory where an erb template file is saved is set. The tpl directory of the project directory is set up by the default.
@@tpl_ext.
The extension of an erb template file is set up. a default value is "html".
The instance variables of Seasar::CGI::Page class is shown below. You are able to use them in get/post method.
@cgi.
cgi instance is set. (cgi is the attachment library of ruby)
@contents.
response contents is set. The result string value of puts, p, render method is added.
@auto_render.
It is set up by Boolean whether a render method is called automatically, when the size of @contents is 0 after calling get/post method.
@auto_response.
It is set up by Boolean whether @contents is outputted by @cgi.out, after calling get/post method.
@headers.
The HTTP headers are set as Hash, which are outputted by @cgi.out at the time of auto_response.
In Page class, next processing of WEB layer is performed.
If "get" method is defined in Page class, it will be called when a request method is GET. "post" method is also the same, it will be called when a request method is POST. As an example, let's create the following cgi script.
% cat public/cgi/quick5.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/cgi.rb' class Page < Seasar::CGI::Page s2comp def get puts 'Hello World 5' end end Seasar::CGI.run %
Please browse http://localhost/s2cgi/cgi/quick5.cgi, you can see "Hello World 5". puts method and p method are overridden in Seasar::CGI::Page. The puts method adds String expression of an object to the response contents. The p method adds inspection of an object to the response contents. When the size of response contents is not 0, since automatic reading of an erb template file is not performed, it does not need to prepare an erb template file with the above-mentioned sample.
The param method returns the request parameter of the key specified by the argument. When the key does not exist in the request parameter, nil is returned. When two or more keys exist, Array instance is returned.
param(name)
The param method is used also when verifying a request parameter. Please refer to it for the validation setup here.
Seasar::CGI::Page#render method processes an erb template file, and adds a string result to @contents. An erb template file can be specified by an argument. Specification of an erb template file is specified with the relative path below the directory specified by @@tpl_dir (class variable). It is as follows when specifying "@@tpl_dir/cgi/quick6.html" template file.
render 'cgi/quick6'
When an argument is omitted, the relative path excluding BASE_URL from SCRIPT_NAME is used. When SCRIPT_NAME is "/s2cgi/cgi/quick6.cgi", and BASE_URL is "/s2cgi", then an erb template will be "cgi/quick6". @@tpl_ext value is used for the extension of a template file.
The render method searches a layout file automatically. It does not process a template file, when a layout file is found. A layout file is processed as a template file. In search of a layout file, it is checked whether the file which added "_layout" to the template file exists. When it does not exist, it is checked whether the file "layout" exists in the same directory as a template file. When a template file is "cgi/quick6", It checks whether "cgi/quick6_layout" exists first, and when it does not exist, it checks whether "cgi/layout" exists.
Seasar::CGI::Page#partial method processes an erb template file, and return a string result. An erb template file can be specified by an argument. It is used, when reading the template of main contents within a layout file or dividing a template file partially. When you specify the template file of main contents within a layout file, please specify @template instance variable as an argument.
<!-- layout file --> <%= partial(@template) %> # include main contents
Seasar::CGI::Page#redirect method redirects by setting URL specified by the argument as Location of a HTTP header. After carrying out redirection, exit is performed and CGI script is ended. The request parameter at the time of redirection can be set up as Hash by the second argument.
redirect('http://xxx.com/index.cgi', :year => 2009)
The validate method receives the block including the procedure which verifies a request parameter. In the first argument, :all, :get, and :post can be specified and it can specify at the time of access of which request method it verifies. Validate block must return Boolean as a return value. When a return value is False, the call of the get/post method corresponding to a request method is not performed.
class Page < Seasar::CGI::Page validate { # same as :all. performs in GET and POST request. param :year, :numeric valid? } validate(:get) { # performs in GET request. param :year, :numeric valid? } validate(:post) { # performs in POST request. param :year, :numeric valid? } end
Within Block passed to a validate method, in order to verify a request parameter, the following method can be used.
param(name, type = nil, options = nil)
- 1st: key of request parameter
- 2nd: type of validation
- 3rd: options passed to validation methodン
A request parameter is specified by name and the verification method to apply is specified by type. Two or more validation types can be registered into one request parameter.
valid? method.
valid?(name = nil, type = nil)
- 1st: key of request parameter
- 2nd: type of validation
- return: Boolean
It returns True, If all the registration entries corresponding to a name and a type which are specified by arguments are valid. It returns False when there is at least one Error. When Argument name is nil, the registration entry corresponding to a type is applicable. When Argument type is nil, the registration entry corresponding to a name is applicable. When both name and type are nil, all the registration entries are applicable.
valids method.
valids(name = nil, type = nil)
- 1st: key of request parameter
- 2nd: type of validation
- return: Array of Seasar::Validate::Entry instance
It returns array of entries with valid validation result within the entries which were searched with the name and the type specified by arguments.
error? method.
error?(name = nil, type = nil)
- 1st: key of request parameter
- 2nd: type of validation
- return: Boolean
It returns True, If there is at least one Error within the registration entries corresponding to the name and the type which are specified by arguments. It returns False when all the entries are valid.
As follows, you can use it within an erb template file.
username : <input type="text" name="username" value=""/> <% if error?(:username) %><span class="err_msg">error message.</span><% end %>
errors method.
errors(name = nil, type = nil)
- 1st: key of request parameter
- 2nd: type of validation
- return: Array of Seasar::Validate::Entry instance
It returns array of entries with Error validation result within the entries which were searched with the name and the type specified by arguments.
if_errors method.
if_errors(name = nil, type = nil, &procedure)
- 1st: key of request parameter
- 2nd: type of validation
- 3nd: block
If there is at least one Error within the registration entries corresponding to the name and the type which are specified by arguments, it passes all the error entry to the block and calls it.
As follows, you can use it within an erb template file.
<% if_errors do |errors| %> <%=h errors.size %> invalid parameters are found. <% end %>
The method used for every validation type is defined in Seasar::Validate::Utils module. A method name becomes the name which added "?" to the validation type. A method name becomes "int?" when a validation type is ":int."
Moreover, the procedure object registered into Seasar::Validate::Utils::Validators Hash is also used. Symbol specified by a validation type is used as a Hash key.
:int.
It is verified whether it is Integer.
The method used is Seasar::Validate::Utils.int?.
An option is specified by Hash. (omissible)The example of param method is as follows.
- :min => Minimum value
- :max => Maximum value
- :include => Include :min、:max value or not. default is True.
- :required => Request parameter must be exists or not. default is True.
param :year, :int, :min => 2000, :max => 2050
:numeric.
It is verified whether it is a numerical string.
The method used is Seasar::Validate::Utils.numeric?.
An option is specified by Hash. (omissible)The example of param method is as follows.
- :min => Minimum value
- :max => Maximum value
- :include => Include :min、:max value or not. default is True.
- :required => Request parameter must be exists or not. default is True.
param :year, :int, :min => 2000, :max => 2050
:string.
It is verified whether it is String.
The method used is Seasar::Validate::Utils.string?.
An option is specified by Hash. (omissible)The example of param method is as follows.
- :min => Minimum length
- :max => Maximum length
- :include => Include :min、:max value or not. default is True.
- :required => Request parameter must be exists or not. default is True.
param :name, :string, :min => 6, :max => 8
:array.
It is verified whether it is Array.
The method used is Seasar::Validate::Utils.array?.
An option is specified by Hash. (omissible)The example of param method is as follows.
- :min => Minimum size
- :max => Maximum size
- :include => Include :min、:max value or not. default is True.
- :required => Request parameter must be exists or not. default is True.
param :names, :array, :min => 6, :max => 8
:member, :in.
It is verified whether it is member of array specified as an option.
The method used is Seasar::Validate::Utils.member?.
An option is specified by Hash or Array.The example of param method is as follows.
- :items => Member Array
- :required => Request parameter must be exists or not. default is True.
param :names, :member, %w[foo bar hoge huga]
:regexp.
It is verified whether Regexp specified as an option is matched.
The method used is Seasar::Validate::Utils.regexp?.
An option is specified by Hash or Regexp.The example of param method is as follows.
- :regexp => Regexp
- :required => Request parameter must be exists or not. default is True.
param :name, :regexp, /^abc/
:alpha.
It verifies whether it is an alphabetical-letter sequence.
The method used is Seasar::Validate::Utils.alpha?.
An option is specified by Hash. (omissible)The example of param method is as follows.
- :case => :down or :up
- :required => Request parameter must be exists or not. default is True.
param :name, :alpha, :case => :down
Instead of registering verification block by a validate method, Validation can be performed by defining a validate_get method to GET access, or defining a validate_post method to POST access.
class Page < Seasar::CGI::Page def validate_get # performs in GET request. param :year, :numeric valid? end def validate_post # performs in POST request. param :year, :numeric valid? end end
The session of S2CGI, CGI::Session of a Ruby attachment library is used. The Hash value set as Session.options is used for the option passed to the argument of a new method. By the default, it is set up as follows within config/cgi.rb.
Seasar::CGI::Session.options = {'tmpdir' => SESSION_DIR, 'database_manager' => CGI::Session::PStore}
Seasar::CGI::Page#get_session method.
CGI::Session is generated and returned. nil is returned when the session is not started.
Seasar::CGI::Page#start_session method.
The new instance of CGI::Session is returned.
If Page class defined within a CGI script file is registered as a component Seasar::CGI.run method will get the registered Page component from S2Container, and will perform it. A setup of DI is also performed in a Page class.
Let's create following service class in a lib/example directory.
% cat lib/example/some-service.rb module Example class SomeService s2comp def add(a, b) return a + b end end end
Please create the following CGI scripts. In Page class, ":some_service" accessor method which receives SomeService instance is defined.
% cat public/cgi/quick6.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/cgi.rb' require 'example/some-service' class Page < Seasar::CGI::Page s2comp attr_accessor :some_service def get puts '1 + 2 = ' + @some_service.add(1, 2).to_s end end Seasar::CGI.run %
Please browse http://localhost/s2cgi/cgi/quick6.cgi, you can see "1 + 2 = 3".
Please create UnitTest of the service class or the logic class in the test directory.
As follows, you can run UnitTest created in the test directory by test-suite.rb.
% ruby test/test-suite.rb Loaded suite . Started ... Finished in 0.001 seconds. 3 tests, 8 assertions, 0 failures, 0 errors %
Starting of CGI Framework will be done by calling Seasar::Rack::CGI.run method. As an example, let's create the following quick1.cgi in public/rack directory.
% cat public/rack/quick1.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/rack.rb' Seasar::Rack::CGI.run %Next, the erb template file of quick1.cgi is created as quick1.html in a tpl/rack directory.% cat tpl/rack/quick1.html Hello World %Please browse http://localhost/s2cgi/rack/quick1.cgi, you can see "Hello World".
You can set the instance of Seasar::Rack::CGI::Page class as the argument of Seasar::CGI.run method. As an example, let's create the following quick2.cgi in public/rack directory.
% cat public/rack/quick2.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/rack.rb' class Page < Seasar::Rack::CGI::Page; end Seasar::Rack::CGI.run(Page.new) %Next, the erb template file of quick2.cgi is created as quick2.html in a tpl/rack directory.% cat tpl/cgi/quick2.html Hello World 2 %Please browse http://localhost/s2cgi/rack/quick2.cgi, you can see "Hello World 2".Seasar::Rack::CGI.run method gets the component of Seasar::Rack::CGI::Page class from S2Container, when an argument is nil. When the component of Seasar::Rack::CGI::Page class does not exist in a container, the instance of Seasar::Rack::CGI::Page class is generated automatically.
@env.
Rack environment argument passed to Seasar::Rack::CGI::Page#call method is set.
@request.
Rack::Request instance is set.
@response.
Rack::Response instance is set. @response.finish method is automatically called after a call of a get/post method.
@auto_render.
It is set up by Boolean whether a render method is called automatically, when the size of @response.body.size is 0 and @response.status is 200 after calling get/post method.
The procedure object which performs Rack Up is set as Seasar::Rack::CGI::Page.rack class variable. As a default value, it is set up as follows in config/rack.rb.Seasar::Rack::CGI::Page.rack {|page| Rack::Builder.app do use Seasar::Rack::CGI::Stdin2StringIO use Rack::ShowStatus use Rack::ShowExceptions use Rack::MethodOverride use Rack::ContentLength use Rack::Session::Cookie run page end }Rack Up procedure object is called within a CGI.run method. The Page instance gotten from S2Container or the Page instance generated newly is passed as an argument.
Moreover, Rack Up procedure object can be set up also as a block argument of Seasar::Rack::CGI.run method.% cat public/rack/quick3.cgi #!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../config/rack.rb' class Page < Seasar::Rack::CGI::Page s2comp def get puts 'Hello World 3' end end Seasar::Rack::CGI.run {|page| Rack::Builder.app do use Seasar::Rack::CGI::Stdin2StringIO run page end } %
© Copyright The Seasar Foundation and the others 2008-2009, all rights reserved. |