aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2004-11-24 01:04:44 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2004-11-24 01:04:44 +0000
commitdb045dbbf60b53dbe013ef25554fd013baf88134 (patch)
tree257830e3c76458c8ff3d1329de83f32b23926028 /railties/lib
downloadrails-db045dbbf60b53dbe013ef25554fd013baf88134.tar.gz
rails-db045dbbf60b53dbe013ef25554fd013baf88134.tar.bz2
rails-db045dbbf60b53dbe013ef25554fd013baf88134.zip
Initial
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/code_statistics.rb71
-rw-r--r--railties/lib/dispatcher.rb55
-rw-r--r--railties/lib/generator.rb112
-rw-r--r--railties/lib/webrick_server.rb159
4 files changed, 397 insertions, 0 deletions
diff --git a/railties/lib/code_statistics.rb b/railties/lib/code_statistics.rb
new file mode 100644
index 0000000000..53e7feb1c0
--- /dev/null
+++ b/railties/lib/code_statistics.rb
@@ -0,0 +1,71 @@
+class CodeStatistics
+ def initialize(*pairs)
+ @pairs = pairs
+ @statistics = calculate_statistics
+ @total = calculate_total if pairs.length > 1
+ end
+
+ def to_s
+ print_header
+ @statistics.each{ |k, v| print_line(k, v) }
+ print_splitter
+
+ if @total
+ print_line("Total", @total)
+ print_splitter
+ end
+ end
+
+ private
+ def calculate_statistics
+ @pairs.inject({}) { |stats, pair| stats[pair.first] = calculate_directory_statistics(pair.last); stats }
+ end
+
+ def calculate_directory_statistics(directory, pattern = /.*rb/)
+ stats = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
+
+ Dir.foreach(directory) do |file_name|
+ next unless file_name =~ pattern
+
+ f = File.open(directory + "/" + file_name)
+
+ while line = f.gets
+ stats["lines"] += 1
+ stats["classes"] += 1 if line =~ /class [A-Z]/
+ stats["methods"] += 1 if line =~ /def [a-z]/
+ stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
+ end
+ end
+
+ stats
+ end
+
+ def calculate_total
+ total = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
+ @statistics.each_value { |pair| pair.each { |k, v| total[k] += v } }
+ total
+ end
+
+ def print_header
+ print_splitter
+ puts "| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |"
+ print_splitter
+ end
+
+ def print_splitter
+ puts "+----------------------+-------+-------+---------+---------+-----+-------+"
+ end
+
+ def print_line(name, statistics)
+ m_over_c = (statistics["methods"] / statistics["classes"]) rescue m_over_c = 0
+ loc_over_m = (statistics["codelines"] / statistics["methods"]) - 2 rescue loc_over_m = 0
+
+ puts "| #{name.ljust(20)} " +
+ "| #{statistics["lines"].to_s.rjust(5)} " +
+ "| #{statistics["codelines"].to_s.rjust(5)} " +
+ "| #{statistics["classes"].to_s.rjust(7)} " +
+ "| #{statistics["methods"].to_s.rjust(7)} " +
+ "| #{m_over_c.to_s.rjust(3)} " +
+ "| #{loc_over_m.to_s.rjust(5)} |"
+ end
+end \ No newline at end of file
diff --git a/railties/lib/dispatcher.rb b/railties/lib/dispatcher.rb
new file mode 100644
index 0000000000..aa7ae98edd
--- /dev/null
+++ b/railties/lib/dispatcher.rb
@@ -0,0 +1,55 @@
+#--
+# Copyright (c) 2004 David Heinemeier Hansson
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+class Dispatcher
+ DEFAULT_SESSION_OPTIONS = { "database_manager" => CGI::Session::PStore, "prefix" => "ruby_sess.", "session_path" => "/" }
+
+ def self.dispatch(cgi = CGI.new, session_options = DEFAULT_SESSION_OPTIONS, error_page = nil)
+ begin
+ request = ActionController::CgiRequest.new(cgi, session_options)
+ response = ActionController::CgiResponse.new(cgi)
+
+ controller_name = request.parameters["controller"].gsub(/[^_a-zA-Z0-9]/, "").untaint
+
+ if module_name = request.parameters["module"]
+ Module.new do
+ ActionController::Base.require_or_load "#{module_name}/#{Inflector.underscore(controller_name)}_controller"
+ Object.const_get("#{Inflector.camelize(controller_name)}Controller").process(request, response).out
+ end
+ else
+ ActionController::Base.require_or_load "#{Inflector.underscore(controller_name)}_controller"
+ Object.const_get("#{Inflector.camelize(controller_name)}Controller").process(request, response).out
+ end
+ rescue Exception => e
+ begin
+ ActionController::Base.logger.info "\n\nException throw during dispatch: #{e.message}\n#{e.backtrace.join("\n")}"
+ rescue Exception
+ # Couldn't log error
+ end
+
+ if error_page then cgi.out{ IO.readlines(error_page) } else raise e end
+ ensure
+ ActiveRecord::Base.reset_associations_loaded
+ end
+ end
+end
diff --git a/railties/lib/generator.rb b/railties/lib/generator.rb
new file mode 100644
index 0000000000..28b41c60f0
--- /dev/null
+++ b/railties/lib/generator.rb
@@ -0,0 +1,112 @@
+require 'fileutils'
+require 'active_record/support/inflector'
+
+module Generator
+ class GeneratorError < StandardError; end
+
+ class Base
+ @@template_root = File.dirname(__FILE__) + '/../generators/templates'
+ cattr_accessor :template_root
+
+ attr_reader :rails_root, :class_name, :file_name, :table_name,
+ :actions, :options
+
+ def initialize(rails_root, object_name, actions = [], options = {})
+ @rails_root = rails_root
+ @class_name = Inflector.camelize(object_name)
+ @file_name = Inflector.underscore(@class_name)
+ @table_name = Inflector.pluralize(@file_name)
+ @actions = actions
+ @options = options
+
+ # Use local templates if rails_root/generators directory exists.
+ local_template_root = File.join(@rails_root, 'generators')
+ if File.directory?(local_template_root)
+ self.class.template_root = local_template_root
+ end
+ end
+
+ protected
+
+ # Generate a file in a fresh Rails app from an ERB template.
+ # Takes a template path relative to +template_root+, a
+ # destination path relative to +rails_root+, evaluates the template,
+ # and writes the result to the destination.
+ def generate_file(template_file_path, rails_file_path, eval_binding = nil)
+ # Determine full paths for source and destination files.
+ template_path = File.join(template_root, template_file_path)
+ rails_path = File.join(rails_root, rails_file_path)
+
+ # Create destination directories.
+ FileUtils.mkdir_p(File.dirname(rails_path))
+
+ # Render template and write result.
+ eval_binding ||= binding
+ contents = ERB.new(File.read(template_path), nil, '-').result(eval_binding)
+ File.open(rails_path, 'w') { |file| file.write(contents) }
+ end
+ end
+
+ # Generate controller, helper, functional test, and views.
+ class Controller < Base
+ def generate
+ options[:scaffold] = file_name if options[:scaffold]
+
+ # Controller class.
+ generate_file "controller.erb", "app/controllers/#{file_name}_controller.rb"
+
+ # Helper class.
+ generate_file "helper.erb", "app/helpers/#{file_name}_helper.rb"
+
+ # Function test.
+ generate_file "controller_test.erb", "test/functional/#{file_name}_controller_test.rb"
+
+ # View template for each action.
+ @actions.each do |action|
+ generate_file "controller_view.rhtml",
+ "app/views/#{file_name}/#{action}.rhtml",
+ binding
+ end
+ end
+ end
+
+ # Generate model, unit test, and fixtures.
+ class Model < Base
+ def generate
+
+ # Model class.
+ generate_file "model.erb", "app/models/#{file_name}.rb"
+
+ # Model unit test.
+ generate_file "model_test.erb", "test/unit/#{file_name}_test.rb"
+
+ # Test fixtures directory.
+ FileUtils.mkdir_p("test/fixtures/#{table_name}")
+ end
+ end
+
+ # Generate mailer, helper, functional test, and views.
+ class Mailer < Base
+ def generate
+
+ # Mailer class.
+ generate_file "mailer.erb", "app/models/#{file_name}.rb"
+
+ # Mailer unit test.
+ generate_file "mailer_test.erb", "test/unit/#{file_name}_test.rb"
+
+ # Test fixtures directory.
+ FileUtils.mkdir_p("test/fixtures/#{table_name}")
+
+ # View template and fixture for each action.
+ @actions.each do |action|
+ generate_file "mailer_action.rhtml",
+ "app/views/#{file_name}/#{action}.rhtml",
+ binding
+ generate_file "mailer_fixture.rhtml",
+ "test/fixtures/#{table_name}/#{action}",
+ binding
+ end
+ end
+ end
+end
diff --git a/railties/lib/webrick_server.rb b/railties/lib/webrick_server.rb
new file mode 100644
index 0000000000..66c78fbd5f
--- /dev/null
+++ b/railties/lib/webrick_server.rb
@@ -0,0 +1,159 @@
+# Donated by Florian Gross
+
+require 'webrick'
+require 'cgi'
+require 'stringio'
+
+begin
+ require 'dev-utils/debug'
+ require 'irb/completion'
+
+ module DevUtils::Debug
+ alias_method :breakpoint_without_io, :breakpoint unless method_defined?(:breakpoint_without_io)
+
+ def breakpoint(name = nil, context = nil, &block)
+ $new_stdin, $new_stdout = $stdin, $stdout
+ $stdin, $stdout = $old_stdin, $old_stdout
+ breakpoint_without_io(name, context, &block)
+ $stdin, $stdout = $new_stdin, $new_stdout
+ end
+ end
+rescue LoadError
+ # dev utils not available
+end
+
+include WEBrick
+
+class DispatchServlet < WEBrick::HTTPServlet::AbstractServlet
+ REQUEST_MUTEX = Mutex.new
+
+ def self.dispatch(options = {})
+ Socket.do_not_reverse_lookup = true # patch for OS X
+
+ server = WEBrick::HTTPServer.new(:Port => options[:port].to_i, :ServerType => options[:server_type], :BindAddress => options[:ip])
+ server.mount('/', DispatchServlet, options)
+
+ trap("INT") { server.shutdown }
+ server.start
+ end
+
+ def initialize(server, options)
+ @server_options = options
+ @file_handler = WEBrick::HTTPServlet::FileHandler.new(server, options[:server_root], {:FancyIndexing => true })
+ super
+ end
+
+ def do_GET(req, res)
+ begin
+ REQUEST_MUTEX.lock
+
+ unless handle_index(req, res)
+ unless handle_dispatch(req, res)
+ unless handle_file(req, res)
+ unless handle_mapped(req, res)
+ raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found."
+ end
+ end
+ end
+ end
+ ensure
+ REQUEST_MUTEX.unlock
+ end
+ end
+
+ alias :do_POST :do_GET
+
+ def handle_index(req, res)
+ if req.request_uri.path == "/"
+ if @server_options[:index_controller]
+ res.set_redirect WEBrick::HTTPStatus::MovedPermanently, "/#{@server_options[:index_controller]}/"
+ else
+ res.set_redirect WEBrick::HTTPStatus::MovedPermanently, "/_doc/index.html"
+ end
+
+ return true
+ else
+ return false
+ end
+ end
+
+ def handle_file(req, res)
+ begin
+ @file_handler.send(:do_GET, req, res)
+ return true
+ rescue HTTPStatus::PartialContent, HTTPStatus::NotModified => err
+ res.set_error(err)
+ return true
+ rescue => err
+ p err
+ return false
+ end
+ end
+
+ def handle_mapped(req, res)
+ parsed_ok, controller, action, id = DispatchServlet.parse_uri(req.request_uri.path)
+ if parsed_ok
+ query = "controller=#{controller}&action=#{action}&id=#{id}"
+ query << "&#{req.request_uri.query}" if req.request_uri.query
+ origin = req.request_uri.path + "?" + query
+ req.request_uri.path = "/dispatch.rb"
+ req.request_uri.query = query
+ handle_dispatch(req, res, origin)
+ else
+ return false
+ end
+ end
+
+ def handle_dispatch(req, res, origin = nil)
+ return false unless /^\/dispatch\.(?:cgi|rb|fcgi)$/.match(req.request_uri.path)
+
+ env = req.meta_vars.clone
+ env["QUERY_STRING"] = req.request_uri.query
+ env["REQUEST_URI"] = origin if origin
+
+ data = nil
+ $old_stdin, $old_stdout = $stdin, $stdout
+ $stdin, $stdout = StringIO.new(req.body || ""), StringIO.new
+
+ begin
+ require 'cgi'
+ CGI.send(:define_method, :env_table) { env }
+
+ load File.join(@server_options[:server_root], "dispatch.rb")
+
+ $stdout.rewind
+ data = $stdout.read
+ ensure
+ $stdin, $stdout = $old_stdin, $old_stdout
+ end
+
+ raw_header, body = *data.split(/^[\xd\xa]+/on, 2)
+ header = WEBrick::HTTPUtils::parse_header(raw_header)
+ if /^(\d+)/ =~ header['status'][0]
+ res.status = $1.to_i
+ header.delete('status')
+ end
+ header.each { |key, val| res[key] = val.join(", ") }
+
+ res.body = body
+ return true
+ rescue => err
+ p err, err.backtrace
+ return false
+ end
+
+ def self.parse_uri(path)
+ component = /([-_a-zA-Z0-9]+)/
+
+ case path.sub(%r{^/(?:fcgi|mruby|cgi)/}, "/")
+ when %r{^/#{component}/?$} then
+ [true, $1, "index", nil]
+ when %r{^/#{component}/#{component}/?$} then
+ [true, $1, $2, nil]
+ when %r{^/#{component}/#{component}/#{component}/?$} then
+ [true, $1, $2, $3]
+ else
+ [false, nil, nil, nil]
+ end
+ end
+end