aboutsummaryrefslogtreecommitdiffstats
path: root/railties
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
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')
-rw-r--r--railties/CHANGELOG265
-rw-r--r--railties/MIT-LICENSE20
-rw-r--r--railties/README121
-rw-r--r--railties/Rakefile279
-rwxr-xr-xrailties/bin/rails28
-rwxr-xr-xrailties/configs/apache.conf31
-rw-r--r--railties/configs/database.yml20
-rwxr-xr-xrailties/dispatches/dispatch.fcgi7
-rwxr-xr-xrailties/dispatches/dispatch.rb10
-rw-r--r--railties/dispatches/dispatch.servlet49
-rw-r--r--railties/dispatches/start_server1
-rw-r--r--railties/doc/README_FOR_APP2
-rw-r--r--railties/doc/apache_protection3
-rw-r--r--railties/doc/index.html94
-rw-r--r--railties/environments/development.rb2
-rw-r--r--railties/environments/production.rb6
-rw-r--r--railties/environments/shared.rb35
-rw-r--r--railties/environments/shared_for_gem.rb23
-rw-r--r--railties/environments/test.rb2
-rwxr-xr-xrailties/fresh_rakefile104
-rwxr-xr-xrailties/generators/new_controller.rb43
-rwxr-xr-xrailties/generators/new_crud.rb34
-rw-r--r--railties/generators/new_mailer.rb43
-rwxr-xr-xrailties/generators/new_model.rb31
-rw-r--r--railties/generators/templates/controller.erb19
-rw-r--r--railties/generators/templates/controller_test.erb17
-rw-r--r--railties/generators/templates/controller_view.rhtml10
-rw-r--r--railties/generators/templates/helper.erb2
-rw-r--r--railties/generators/templates/mailer.erb15
-rw-r--r--railties/generators/templates/mailer_action.rhtml3
-rw-r--r--railties/generators/templates/mailer_fixture.rhtml4
-rw-r--r--railties/generators/templates/mailer_test.erb37
-rw-r--r--railties/generators/templates/model.erb2
-rw-r--r--railties/generators/templates/model_test.erb11
-rw-r--r--railties/helpers/abstract_application.rb5
-rw-r--r--railties/helpers/application_helper.rb3
-rw-r--r--railties/helpers/test_helper.rb16
-rw-r--r--railties/html/404.html6
-rw-r--r--railties/html/500.html6
-rw-r--r--railties/html/index.html1
-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
-rw-r--r--railties/test/webrick_dispatcher_test.rb30
45 files changed, 1837 insertions, 0 deletions
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
new file mode 100644
index 0000000000..60eb1c3e2a
--- /dev/null
+++ b/railties/CHANGELOG
@@ -0,0 +1,265 @@
+*CVS*
+
+* Added breakpoint support by default to the WEBrick dispatcher. This means that you can break out of execution at any point in
+ the code, investigate and change the model, AND then resume execution! Example:
+
+ class WeblogController < ActionController::Base
+ def index
+ @posts = Post.find_all
+ breakpoint "Breaking out from the list"
+ end
+ end
+
+ So the controller will accept the action, run the first line, then present you with a IRB prompt in the WEBrick window (you shouldn't
+ run as daemon when you want to use this). Here you can do things like:
+
+ Executing breakpoint "Breaking out from the list" at .../webrick_server.rb:16 in 'breakpoint'
+
+ >> @posts.inspect
+ => "[#<Post:0x14a6be8 @attributes={\"title\"=>nil, \"body\"=>nil, \"id\"=>\"1\"}>,
+ #<Post:0x14a6620 @attributes={\"title\"=>\"Rails you know!\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]"
+ >> @posts.first.title = "hello from a breakpoint"
+ => "hello from a breakpoint"
+
+ ...and even better is that you can examine how your runtime objects actually work:
+
+ >> f = @posts.first
+ => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
+ >> f.
+ Display all 152 possibilities? (y or n)
+
+ Finally, when you're ready to resume execution, you press CTRL-D
+
+* Changed environments to be configurable through an environment variable. By default, the environment is "development", but you
+ can change that and set your own by configuring the Apache vhost with a string like (mod_env must be available on the server):
+
+ SetEnv RAILS_ENV production
+
+ ...if you're using WEBrick, you can pick the environment to use with the command-line parameters -e/--environment, like this:
+
+ ruby public/dispatcher.servlet -e production
+
+* Added a new default environment called "development", which leaves the production environment to be tuned exclusively for that.
+
+* Added a start_server in the root of the Rails application to make it even easier to get started
+
+* Fixed public/.htaccess to use RewriteBase and share the same rewrite rules for all the dispatch methods
+
+* Fixed webrick_server to handle requests in a serialized manner (the Rails reloading infrastructure is not thread-safe)
+
+* Added support for controllers in directories. So you can have:
+
+ app/controllers/account_controller.rb # URL: /account/
+ app/controllers/admin/account_controller.rb # URL: /admin/account/
+
+ NOTE: You need to update your public/.htaccess with the new rules to pick it up
+
+* Added reloading for associations and dependencies under cached environments like FastCGI and mod_ruby. This makes it possible to use
+ those environments for development. This is turned on by default, but can be turned off with
+ ActiveRecord::Base.reload_associations = false and ActionController::Base.reload_dependencies = false in production environments.
+
+* Added support for sub-directories in app/models. So now you can have something like Basecamp with:
+
+ app/models/accounting
+ app/models/project
+ app/models/participants
+ app/models/settings
+
+ It's poor man's namespacing, but only for file-system organization. You still require files just like before.
+ Nothing changes inside the files themselves.
+
+
+* Fixed a few references in the tests generated by new_mailer [bitsweat]
+
+* Added support for mocks in testing with test/mocks
+
+* Cleaned up the environments a bit and added global constant RAILS_ROOT
+
+
+*0.8.5* (9)
+
+* Made dev-util available to all tests, so you can insert breakpoints in any test case to get an IRB prompt at that point [bitsweat]:
+
+ def test_complex_stuff
+ @david.projects << @new_project
+ breakpoint "Let's have a closer look at @david"
+ end
+
+ You need to install dev-utils yourself for this to work ("gem install dev-util").
+
+* Added shared generator behavior so future upgrades should be possible without manually copying over files [bitsweat]
+
+* Added the new helper style to both controller and helper templates [bitsweat]
+
+* Added new_crud generator for creating a model and controller at the same time with explicit scaffolding [bitsweat]
+
+* Added configuration of Test::Unit::TestCase.fixture_path to test_helper to concide with the new AR fixtures style
+
+* Fixed that new_model was generating singular table/fixture names
+
+* Upgraded to Action Mailer 0.4.0
+
+* Upgraded to Action Pack 0.9.5
+
+* Upgraded to Active Record 1.1.0
+
+
+*0.8.0 (15)*
+
+* Removed custom_table_name option for new_model now that the Inflector is as powerful as it is
+
+* Changed the default rake action to just do testing and separate API generation and coding statistics into a "doc" task.
+
+* Fixed WEBrick dispatcher to handle missing slashes in the URLs gracefully [alexey]
+
+* Added user option for all postgresql tool calls in the rakefile [elvstone]
+
+* Fixed problem with running "ruby public/dispatch.servlet" instead of "cd public; ruby dispatch.servlet" [alexey]
+
+* Fixed WEBrick server so that it no longer hardcodes the ruby interpreter used to "ruby" but will get the one used based
+ on the Ruby runtime configuration. [Marcel Molina Jr.]
+
+* Fixed Dispatcher so it'll route requests to magic_beans to MagicBeansController/magic_beans_controller.rb [Caio Chassot]
+
+* "new_controller MagicBeans" and "new_model SubscriptionPayments" will now both behave properly as they use the new Inflector.
+
+* Fixed problem with MySQL foreign key constraint checks in Rake :clone_production_structure_to_test target [Andreas Schwarz]
+
+* Changed WEBrick server to by default be auto-reloading, which is slower but makes source changes instant.
+ Class compilation cache can be turned on with "-c" or "--cache-classes".
+
+* Added "-b/--binding" option to WEBrick dispatcher to bind the server to a specific IP address (default: 127.0.0.1) [Kevin Temp]
+
+* dispatch.fcgi now DOESN'T set FCGI_PURE_RUBY as it was slowing things down for now reason [Andreas Schwarz]
+
+* Added new_mailer generator to work with Action Mailer
+
+* Included new framework: Action Mailer 0.3
+
+* Upgraded to Action Pack 0.9.0
+
+* Upgraded to Active Record 1.0.0
+
+
+*0.7.0*
+
+* Added an optional second argument to the new_model script that allows the programmer to specify the table name,
+ which will used to generate a custom table_name method in the model and will also be used in the creation of fixtures.
+ [Kevin Radloff]
+
+* script/new_model now turns AccountHolder into account_holder instead of accountholder [Kevin Radloff]
+
+* Fixed the faulty handleing of static files with WEBrick [Andreas Schwarz]
+
+* Unified function_test_helper and unit_test_helper into test_helper
+
+* Fixed bug with the automated production => test database dropping on PostgreSQL [dhawkins]
+
+* create_fixtures in both the functional and unit test helper now turns off the log during fixture generation
+ and can generate more than one fixture at a time. Which makes it possible for assignments like:
+
+ @people, @projects, @project_access, @companies, @accounts =
+ create_fixtures "people", "projects", "project_access", "companies", "accounts"
+
+* Upgraded to Action Pack 0.8.5 (locally-scoped variables, partials, advanced send_file)
+
+* Upgraded to Active Record 0.9.5 (better table_name guessing, cloning, find_all_in_collection)
+
+
+*0.6.5*
+
+* No longer specifies a template for rdoc, so it'll use whatever is default (you can change it in the rakefile)
+
+* The new_model generator will now use the same rules for plural wordings as Active Record
+ (so Category will give categories, not categorys) [Kevin Radloff]
+
+* dispatch.fcgi now sets FCGI_PURE_RUBY to true to ensure that it's the Ruby version that's loaded [danp]
+
+* Made the GEM work with Windows
+
+* Fixed bug where mod_ruby would "forget" the load paths added when switching between controllers
+
+* PostgreSQL are now supported for the automated production => test database dropping [Kevin Radloff]
+
+* Errors thrown by the dispatcher are now properly handled in FCGI.
+
+* Upgraded to Action Pack 0.8.0 (lots and lots and lots of fixes)
+
+* Upgraded to Active Record 0.9.4 (a bunch of fixes)
+
+
+*0.6.0*
+
+* Added AbstractionApplicationController as a superclass for all controllers generated. This class can be used
+ to carry filters and methods that are to be shared by all. It has an accompanying ApplicationHelper that all
+ controllers will also automatically have available.
+
+* Added environments that can be included from any script to get the full Active Record and Action Controller
+ context running. This can be used by maintenance scripts or to interact with the model through IRB. Example:
+
+ require 'config/environments/production'
+
+ for account in Account.find_all
+ account.recalculate_interests
+ end
+
+ A short migration script for an account model that had it's interest calculation strategy changed.
+
+* Accessing the index of a controller with "/weblog" will now redirect to "/weblog/" (only on Apache, not WEBrick)
+
+* Simplified the default Apache config so even remote requests are served off CGI as a default.
+ You'll now have to do something specific to activate mod_ruby and FCGI (like using the force urls).
+ This should make it easier for new comers that start on an external server.
+
+* Added more of the necessary Apache options to .htaccess to make it easier to setup
+
+* Upgraded to Action Pack 0.7.9 (lots of fixes)
+
+* Upgraded to Active Record 0.9.3 (lots of fixes)
+
+
+*0.5.7*
+
+* Fixed bug in the WEBrick dispatcher that prevented it from getting parameters from the URL
+ (through GET requests or otherwise)
+
+* Added lib in root as a place to store app specific libraries
+
+* Added lib and vendor to load_path, so anything store within can be loaded directly.
+ Hence lib/redcloth.rb can be loaded with require "redcloth"
+
+* Upgraded to Action Pack 0.7.8 (lots of fixes)
+
+* Upgraded to Active Record 0.9.2 (minor upgrade)
+
+
+*0.5.6*
+
+* Upgraded to Action Pack 0.7.7 (multipart form fix)
+
+* Updated the generated template stubs to valid XHTML files
+
+* Ensure that controllers generated are capitalized, so "new_controller TodoLists"
+ gives the same as "new_controller Todolists" and "new_controller todolists".
+
+
+*0.5.5*
+
+* Works on Windows out of the box! (Dropped symlinks)
+
+* Added webrick dispatcher: Try "ruby public/dispatch.servlet --help" [Florian Gross]
+
+* Report errors about initialization to browser (instead of attempting to use uninitialized logger)
+
+* Upgraded to Action Pack 0.7.6
+
+* Upgraded to Active Record 0.9.1
+
+* Added distinct 500.html instead of reusing 404.html
+
+* Added MIT license
+
+
+*0.5.0*
+
+* First public release
diff --git a/railties/MIT-LICENSE b/railties/MIT-LICENSE
new file mode 100644
index 0000000000..5919c288e4
--- /dev/null
+++ b/railties/MIT-LICENSE
@@ -0,0 +1,20 @@
+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. \ No newline at end of file
diff --git a/railties/README b/railties/README
new file mode 100644
index 0000000000..4702f8a6c8
--- /dev/null
+++ b/railties/README
@@ -0,0 +1,121 @@
+== Welcome to Rails
+
+Rails is a web-application and persistance framework that includes everything
+needed to create database-backed web-applications according to the
+Model-View-Control pattern of separation. This pattern splits the view (also
+called the presentation) into "dumb" templates that are primarily responsible
+for inserting pre-build data in between HTML tags. The model contains the
+"smart" domain objects (such as Account, Product, Person, Post) that holds all
+the business logic and knows how to persist themselves to a database. The
+controller handles the incoming requests (such as Save New Account, Update
+Product, Show Post) by manipulating the model and directing data to the view.
+
+In Rails, the model is handled by what's called a object-relational mapping
+layer entitled Active Record. This layer allows you to present the data from
+database rows as objects and embellish these data objects with business logic
+methods. You can read more about Active Record in
+link:files/vendor/activerecord/README.html.
+
+The controller and view is handled by the Action Pack, which handles both
+layers by its two parts: Action View and Action Controller. These two layers
+are bundled in a single package due to their heavy interdependence. This is
+unlike the relationship between the Active Record and Action Pack that is much
+more separate. Each of these packages can be used independently outside of
+Rails. You can read more about Action Pack in
+link:files/vendor/actionpack/README.html.
+
+
+== Requirements
+
+* Database and driver (MySQL, PostgreSQL, or SQLite)
+* Rake[http://rake.rubyforge.org] for running tests and the generating documentation
+
+== Optionals
+
+* Apache 1.3.x or 2.x (or any FastCGI-capable webserver with a
+ mod_rewrite-like module)
+* FastCGI (or mod_ruby) for production performance (CGI is used for
+ development)
+
+== Getting started
+
+1a. Setup Apache for the Rails application (see "Example for Apache conf")
+1b. Run the WEBrick servlet: <tt>ruby public/dispatch.servlet --help</tt>
+2. Go to http://rails/ (or whatever is your ServerName) and check
+ that you get the "Congratulations, you're on Rails!" screen
+3. Follow the guidelines on the "Congratulations, you're on Rails!" screen
+
+
+== Example for Apache conf
+
+ <VirtualHost *:80>
+ ServerName rails
+ DocumentRoot /path/tapplication/public/
+ ErrorLog /path/application/log/apache.log
+
+ <Directory /path/application/public/>
+ Options ExecCGI FollowSymLinks
+ AllowOverride all
+ Allow from all
+ Order allow,deny
+ </Directory>
+ </VirtualHost>
+
+NOTE: Be sure that CGIs can be executed in that directory as well. So ExecCGI
+should be on and ".cgi" should respond. All requests from 127.0.0.1 goes
+through CGI, so no Apache restart is necessary for changes. All other requests
+goes through FCGI (or mod_ruby) that requires restart to show changes.
+
+
+== Debugging Rails
+
+Have "tail -f" commands running on both the apache.log, production.log, and
+test.log files. Rails will automatically display debugging and runtime
+information to these files. Debugging info will also be shown in the browser
+on requests from 127.0.0.1.
+
+
+== Description of contents
+
+app
+ Holds all the code that's specific to this particular application.
+
+app/controllers
+ Holds controllers that should be named like weblog_controller.rb for
+ automated URL mapping. All controllers should descend from
+ ActionController::Base.
+
+app/models
+ Holds models that should be named like post.rb.
+ Most models will descent from ActiveRecord::Base.
+
+app/views
+ Holds the template files for the view that should be named like
+ weblog/index.rhtml for the WeblogController#index action. All views uses eRuby
+ syntax. This directory can also be used to keep stylesheets, images, and so on
+ that can be symlinked to public.
+
+app/helpers
+ Holds view helpers that should be named like weblog_helper.rb.
+
+config
+ Configuration files for Apache, database, and other dependencies.
+
+lib
+ Application specific libraries. Basically, any kind of custom code that doesn't
+ belong controllers, models, or helpers. This directory is in the load path.
+
+public
+ The directory available for Apache, which includes symbolic links to other
+ parts of the structure that are to be made available. Refrain from placing
+ actual files in here if you're using CVS and don't want to check in this
+ directory.
+
+script
+ Helper scripts for automation and generation.
+
+test
+ Unit and functional tests along with fixtures.
+
+vendor
+ External libraries that the application depend on. This directory is in the load path.
diff --git a/railties/Rakefile b/railties/Rakefile
new file mode 100644
index 0000000000..aef5a4e884
--- /dev/null
+++ b/railties/Rakefile
@@ -0,0 +1,279 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+require 'rake/gempackagetask'
+require 'rake/contrib/rubyforgepublisher'
+
+require 'date'
+
+
+PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
+PKG_NAME = 'rails'
+PKG_VERSION = '0.8.5' + PKG_BUILD
+PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
+PKG_DESTINATION = ENV["RAILS_PKG_DESTINATION"] || "../#{PKG_NAME}"
+
+desc "Default Task"
+task :default => [ :fresh_rails ]
+
+desc "Generates a fresh Rails package with documentation"
+task :fresh_rails => [ :make_dir_structure, :initialize_file_stubs, :copy_vendor_libraries, :copy_ties_content, :generate_documentation ]
+
+desc "Generates a fresh Rails package using GEMs with documentation"
+task :fresh_gem_rails => [ :make_dir_structure, :initialize_file_stubs, :copy_ties_content, :copy_gem_environment ]
+
+desc "Generates a fresh Rails package without documentation (faster)"
+task :fresh_rails_without_docs => [ :make_dir_structure, :initialize_file_stubs, :copy_vendor_libraries, :copy_ties_content ]
+
+desc "Packages the fresh Rails package with documentation"
+task :package => [ :clean, :fresh_rails ] do
+ system %{cd ..; tar -czvf #{PKG_NAME}-#{PKG_VERSION}.tgz #{PKG_NAME}}
+ system %{cd ..; zip -r #{PKG_NAME}-#{PKG_VERSION}.zip #{PKG_NAME}}
+end
+
+task :clean do
+ File.rm_rf "#{PKG_DESTINATION}"
+end
+
+
+# Make directory structure ----------------------------------------------------------------
+
+desc "Make the directory structure for the new Rails application"
+task :make_dir_structure => [ :make_base_dirs, :make_app_dirs, :make_public_dirs, :make_test_dirs ] do
+end
+
+task :make_base_dirs do
+ File.rm_rf PKG_DESTINATION
+ File.mkdir "#{PKG_DESTINATION}"
+ File.mkdir "#{PKG_DESTINATION}/app"
+ File.mkdir "#{PKG_DESTINATION}/config"
+ File.mkdir "#{PKG_DESTINATION}/config/environments"
+ File.mkdir "#{PKG_DESTINATION}/db"
+ File.mkdir "#{PKG_DESTINATION}/doc"
+ File.mkdir "#{PKG_DESTINATION}/log"
+ File.mkdir "#{PKG_DESTINATION}/lib"
+ File.mkdir "#{PKG_DESTINATION}/public"
+ File.mkdir "#{PKG_DESTINATION}/script"
+ File.mkdir "#{PKG_DESTINATION}/test"
+ File.mkdir "#{PKG_DESTINATION}/vendor"
+end
+
+task :make_app_dirs do
+ File.mkdir "#{PKG_DESTINATION}/app/models"
+ File.mkdir "#{PKG_DESTINATION}/app/controllers"
+ File.mkdir "#{PKG_DESTINATION}/app/helpers"
+ File.mkdir "#{PKG_DESTINATION}/app/views"
+ File.mkdir "#{PKG_DESTINATION}/app/views/layouts"
+end
+
+task :make_public_dirs do
+ File.mkdir "#{PKG_DESTINATION}/public/images"
+ File.mkdir "#{PKG_DESTINATION}/public/javascripts"
+ File.mkdir "#{PKG_DESTINATION}/public/stylesheets"
+ File.mkdir "#{PKG_DESTINATION}/public/_doc"
+end
+
+task :make_test_dirs do
+ File.mkdir "#{PKG_DESTINATION}/test/fixtures"
+ File.mkdir "#{PKG_DESTINATION}/test/unit"
+ File.mkdir "#{PKG_DESTINATION}/test/functional"
+ File.mkdir "#{PKG_DESTINATION}/test/mocks/development"
+ File.mkdir "#{PKG_DESTINATION}/test/mocks/testing"
+end
+
+
+# Initialize file stubs -------------------------------------------------------------------
+
+desc "Initialize empty file stubs (such as for logging)"
+task :initialize_file_stubs => [ :initialize_log_files ] do
+end
+
+task :initialize_log_files do
+ chmod 0777, "#{PKG_DESTINATION}/log"
+
+ File.touch "#{PKG_DESTINATION}/log/apache.log"
+ File.touch "#{PKG_DESTINATION}/log/production.log"
+
+ chmod 0777, "#{PKG_DESTINATION}/log/apache.log"
+ chmod 0777, "#{PKG_DESTINATION}/log/production.log"
+end
+
+
+# Copy Vendors ----------------------------------------------------------------------------
+
+desc "Copy in all the Rails packages to vendor"
+task :copy_vendor_libraries => [ :copy_action_pack, :copy_active_record, :copy_ties, :copy_action_mailer ]
+
+task :copy_action_pack do
+ File.cp_r "../actionpack", "#{PKG_DESTINATION}/vendor/actionpack"
+end
+
+task :copy_active_record do
+ File.cp_r "../activerecord", "#{PKG_DESTINATION}/vendor/activerecord"
+end
+
+task :copy_action_mailer do
+ File.cp_r "../actionmailer", "#{PKG_DESTINATION}/vendor/actionmailer"
+end
+
+task :copy_ties do
+ File.cp_r "../railties", "#{PKG_DESTINATION}/vendor/railties"
+end
+
+
+# Copy Ties Content -----------------------------------------------------------------------
+
+# :link_apache_config
+desc "Make copies of all the default content of ties"
+task :copy_ties_content => [
+ :copy_rootfiles, :copy_dispatches, :copy_html_files, :copy_abstract_application,
+ :copy_configs, :copy_generators, :copy_test_helpers, :copy_docs_in_public,
+ :copy_app_doc_readme ] do
+end
+
+task :copy_dispatches do
+ File.cp "dispatches/dispatch.rb", "#{PKG_DESTINATION}/public/dispatch.rb"
+ chmod 0755, "#{PKG_DESTINATION}/public/dispatch.rb"
+
+ File.cp "dispatches/dispatch.rb", "#{PKG_DESTINATION}/public/dispatch.cgi"
+ chmod 0755, "#{PKG_DESTINATION}/public/dispatch.cgi"
+
+ File.cp "dispatches/dispatch.fcgi", "#{PKG_DESTINATION}/public/dispatch.fcgi"
+ chmod 0755, "#{PKG_DESTINATION}/public/dispatch.fcgi"
+
+ File.cp "dispatches/dispatch.servlet", "#{PKG_DESTINATION}/public/dispatch.servlet"
+
+ File.cp "dispatches/start_server", "#{PKG_DESTINATION}/start_server"
+ chmod 0755, "#{PKG_DESTINATION}/start_server"
+end
+
+task :copy_html_files do
+ File.cp "html/404.html", "#{PKG_DESTINATION}/public/404.html"
+ File.cp "html/500.html", "#{PKG_DESTINATION}/public/500.html"
+ File.cp "html/index.html", "#{PKG_DESTINATION}/public/index.html"
+end
+
+task :copy_abstract_application do
+ File.cp "helpers/abstract_application.rb", "#{PKG_DESTINATION}/app/controllers/abstract_application.rb"
+ File.cp "helpers/application_helper.rb", "#{PKG_DESTINATION}/app/helpers/application_helper.rb"
+end
+
+task :copy_configs do
+ File.cp "configs/database.yml", "#{PKG_DESTINATION}/config/database.yml"
+
+ File.cp "configs/apache.conf", "#{PKG_DESTINATION}/public/.htaccess"
+
+ File.cp "environments/shared.rb", "#{PKG_DESTINATION}/config/environment.rb"
+ File.cp "environments/production.rb", "#{PKG_DESTINATION}/config/environments/production.rb"
+ File.cp "environments/development.rb", "#{PKG_DESTINATION}/config/environments/development.rb"
+ File.cp "environments/test.rb", "#{PKG_DESTINATION}/config/environments/test.rb"
+end
+
+task :copy_generators do
+ File.cp "generators/new_controller.rb", "#{PKG_DESTINATION}/script/new_controller"
+ File.cp "generators/new_model.rb", "#{PKG_DESTINATION}/script/new_model"
+ File.cp "generators/new_mailer.rb", "#{PKG_DESTINATION}/script/new_mailer"
+ File.cp "generators/new_crud.rb", "#{PKG_DESTINATION}/script/new_crud"
+ chmod 0755, "#{PKG_DESTINATION}/script/new_controller"
+ chmod 0755, "#{PKG_DESTINATION}/script/new_model"
+ chmod 0755, "#{PKG_DESTINATION}/script/new_mailer"
+ chmod 0755, "#{PKG_DESTINATION}/script/new_crud"
+end
+
+task :copy_rootfiles do
+ File.cp "fresh_rakefile", "#{PKG_DESTINATION}/Rakefile"
+ File.cp "README", "#{PKG_DESTINATION}/README"
+end
+
+task :copy_test_helpers do
+ File.cp "helpers/test_helper.rb", "#{PKG_DESTINATION}/test/test_helper.rb"
+end
+
+task :copy_docs_in_public do
+ File.cp "doc/index.html", "#{PKG_DESTINATION}/public/_doc/index.html"
+end
+
+task :copy_app_doc_readme do
+ File.cp "doc/README_FOR_APP", "#{PKG_DESTINATION}/doc/README_FOR_APP"
+end
+
+task :link_apache_config do
+ cd "#{PKG_DESTINATION}/config/"
+ ln_s "../public/.htaccess", "apache.conf"
+ cd "../../railties"
+end
+
+
+# Generate documentation ------------------------------------------------------------------
+
+desc "Generate documentation for the framework and for the empty application"
+task :generate_documentation => [ :generate_app_doc, :generate_rails_framework_doc ] do
+end
+
+task :generate_rails_framework_doc do
+ system %{cd #{PKG_DESTINATION}; rake apidoc}
+end
+
+task :generate_app_doc do
+ File.cp "doc/README_FOR_APP", "#{PKG_DESTINATION}/doc/README_FOR_APP"
+ system %{cd #{PKG_DESTINATION}; rake appdoc}
+end
+
+
+# Generate GEM ----------------------------------------------------------------------------
+
+task :copy_gem_environment do
+ File.cp "environments/shared_for_gem.rb", "#{PKG_DESTINATION}/config/environment.rb"
+end
+
+
+PKG_FILES = FileList[
+ '[a-zA-Z]*',
+ 'bin/**/*',
+ 'configs/**/*',
+ 'doc/**/*',
+ 'dispatches/**/*',
+ 'environments/**/*',
+ 'generators/**/*',
+ 'helpers/**/*',
+ 'html/**/*',
+ 'lib/**/*'
+]
+
+spec = Gem::Specification.new do |s|
+ s.name = 'rails'
+ s.version = PKG_VERSION
+ s.summary = "Web-application framework with template engine, control-flow layer, and ORM."
+ s.description = <<-EOF
+ Rails is a framework for building web-application using CGI, FCGI, mod_ruby, or WEBrick
+ on top of either MySQL, PostgreSQL, or SQLite with eRuby-based templates.
+ EOF
+
+ s.add_dependency('rake', '>= 0.4.11')
+ s.add_dependency('activerecord', '>= 1.1.0')
+ s.add_dependency('actionpack', '>= 0.9.5')
+ s.add_dependency('actionmailer', '>= 0.4.0')
+ s.add_dependency('dev-utils', '>= 1.0.1')
+
+ s.files = PKG_FILES.to_a
+ s.require_path = 'lib'
+
+ s.bindir = "bin" # Use these for applications.
+ s.executables = ["rails"]
+ s.default_executable = "rails"
+
+ s.author = "David Heinemeier Hansson"
+ s.email = "david@loudthinking.com"
+ s.homepage = "http://www.rubyonrails.org"
+ s.rubyforge_project = "rails"
+end
+
+Rake::GemPackageTask.new(spec) do |pkg|
+end
+
+# Publish beta gem
+desc "Publish the API documentation"
+task :pgem => [:gem] do
+ Rake::SshFilePublisher.new("davidhh@one.textdrive.com", "domains/rubyonrails.org/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
+ `ssh davidhh@one.textdrive.com './gemupdate.sh'`
+end \ No newline at end of file
diff --git a/railties/bin/rails b/railties/bin/rails
new file mode 100755
index 0000000000..846f02ac69
--- /dev/null
+++ b/railties/bin/rails
@@ -0,0 +1,28 @@
+if ARGV[0]
+ ENV["RAILS_PKG_DESTINATION"] = File.expand_path(ARGV[0])
+ if RUBY_PLATFORM =~ /mswin32/
+ Dir.chdir File.dirname(__FILE__)
+ system %{rake.cmd fresh_gem_rails}
+ else
+ system %{ cd #{File.dirname(__FILE__)}; rake fresh_gem_rails }
+ end
+else
+ puts <<-HELP
+
+NAME
+ rails - creates a new Rails installation
+
+SYNOPSIS
+ rails [full path]
+
+DESCRIPTION
+ This generator will create a suggested directory structure, lots of minor helper
+ files, and a default configuration for creating a new Rails application. Once the
+ generator is done, you're adviced to look at the README in the root of the folder.
+
+EXAMPLE
+ rails ~/Code/Ruby/weblog
+
+ This will generate a new Rails installation in the ~/Code/Ruby/weblog folder.
+HELP
+end \ No newline at end of file
diff --git a/railties/configs/apache.conf b/railties/configs/apache.conf
new file mode 100755
index 0000000000..feb2e32c4e
--- /dev/null
+++ b/railties/configs/apache.conf
@@ -0,0 +1,31 @@
+# General Apache options
+AddHandler fastcgi-script .fcgi
+AddHandler cgi-script .cgi
+Options +FollowSymLinks +ExecCGI
+  
+# Make sure that mod_ruby.c has been added and loaded as a module with Apache
+RewriteEngine On
+# Change extension from .cgi to .fcgi to switch to FCGI and to .rb to switch to mod_ruby
+RewriteBase /dispatch.cgi
+RewriteRule ^dispatch.servlet$ / [R]
+# Enable this rewrite rule to point to the controller/action that should serve root.
+# RewriteRule ^$ /controller/action
+# Add missing slash
+RewriteRule ^([-_a-zA-Z0-9]+)$ /$1/ [R]
+# Default rewriting rules.
+RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ ?controller=$1&action=$2&id=$3 [QSA,L]
+RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ ?controller=$1&action=$2 [QSA,L]
+RewriteRule ^([-_a-zA-Z0-9]+)/$ ?controller=$1&action=index [QSA,L]
+RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ ?module=$1&controller=$2&action=$3&id=$4 [QSA,L]
+RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ ?module=$1&controller=$2&action=$3 [QSA,L]
+RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/$ ?module=$1&controller=$2&action=index [QSA,L]
+# You can also point these error messages to a controller/action
+ErrorDocument 500 /500.html
+ErrorDocument 404 /404.html \ No newline at end of file
diff --git a/railties/configs/database.yml b/railties/configs/database.yml
new file mode 100644
index 0000000000..0f9a7eb20e
--- /dev/null
+++ b/railties/configs/database.yml
@@ -0,0 +1,20 @@
+development:
+ adapter: mysql
+ database: rails_development
+ host: localhost
+ username: root
+ password:
+
+test:
+ adapter: mysql
+ database: rails_test
+ host: localhost
+ username: root
+ password:
+
+production:
+ adapter: mysql
+ database: rails_production
+ host: localhost
+ username: root
+ password:
diff --git a/railties/dispatches/dispatch.fcgi b/railties/dispatches/dispatch.fcgi
new file mode 100755
index 0000000000..dc43f03b19
--- /dev/null
+++ b/railties/dispatches/dispatch.fcgi
@@ -0,0 +1,7 @@
+#!/usr/local/bin/ruby
+
+require File.dirname(__FILE__) + "/../config/environment"
+require 'dispatcher'
+require 'fcgi'
+
+FCGI.each_cgi { |cgi| Dispatcher.dispatch(cgi, Dispatcher::DEFAULT_SESSION_OPTIONS, File.dirname(__FILE__) + "/500.html") } \ No newline at end of file
diff --git a/railties/dispatches/dispatch.rb b/railties/dispatches/dispatch.rb
new file mode 100755
index 0000000000..eb2c95e813
--- /dev/null
+++ b/railties/dispatches/dispatch.rb
@@ -0,0 +1,10 @@
+#!/usr/local/bin/ruby
+
+require File.dirname(__FILE__) + "/../config/environment"
+
+# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
+# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
+require "dispatcher"
+
+ADDITIONAL_LOAD_PATHS.flatten.each { |dir| $:.unshift "#{RAILS_ROOT}/#{dir}" }
+Dispatcher.dispatch \ No newline at end of file
diff --git a/railties/dispatches/dispatch.servlet b/railties/dispatches/dispatch.servlet
new file mode 100644
index 0000000000..a1fa403a67
--- /dev/null
+++ b/railties/dispatches/dispatch.servlet
@@ -0,0 +1,49 @@
+#!/usr/local/bin/ruby
+
+require 'webrick'
+require 'optparse'
+
+OPTIONS = {
+ :port => 3000,
+ :ip => "127.0.0.1",
+ :environment => "development",
+ :server_root => File.expand_path(File.dirname(__FILE__)),
+ :server_type => WEBrick::SimpleServer
+}
+
+ARGV.options do |opts|
+ script_name = File.basename($0)
+ opts.banner = "Usage: ruby #{script_name} [options]"
+
+ opts.separator ""
+
+ opts.on("-p", "--port=port", Integer,
+ "Runs Rails on the specified port.",
+ "Default: 3000") { |OPTIONS[:port]| }
+ opts.on("-b", "--binding=ip", String,
+ "Binds Rails to the specified ip.",
+ "Default: 127.0.0.1") { |OPTIONS[:ip]| }
+ opts.on("-i", "--index=controller", String,
+ "Specifies an index controller that requests for root will go to (instead of congratulations screen)."
+ ) { |OPTIONS[:index_controller]| }
+ opts.on("-e", "--environment=name", String,
+ "Specifies the environment to run this server under (test/development/production).",
+ "Default: development") { |OPTIONS[:environment]| }
+ opts.on("-d", "--daemon",
+ "Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
+ ) { OPTIONS[:server_type] = WEBrick::Daemon }
+
+ opts.separator ""
+
+ opts.on("-h", "--help",
+ "Show this help message.") { puts opts; exit }
+
+ opts.parse!
+end
+
+ENV["RAILS_ENV"] = OPTIONS[:environment]
+require File.dirname(__FILE__) + "/../config/environment"
+require 'webrick_server'
+
+puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
+DispatchServlet.dispatch(OPTIONS) \ No newline at end of file
diff --git a/railties/dispatches/start_server b/railties/dispatches/start_server
new file mode 100644
index 0000000000..c6ecb4e4fe
--- /dev/null
+++ b/railties/dispatches/start_server
@@ -0,0 +1 @@
+ruby public/dispatch.servlet \ No newline at end of file
diff --git a/railties/doc/README_FOR_APP b/railties/doc/README_FOR_APP
new file mode 100644
index 0000000000..ac6c149122
--- /dev/null
+++ b/railties/doc/README_FOR_APP
@@ -0,0 +1,2 @@
+Use this README file to introduce your application and point to useful places in the API for learning more.
+Run "rake appdoc" to generate API documentation for your models and controllers. \ No newline at end of file
diff --git a/railties/doc/apache_protection b/railties/doc/apache_protection
new file mode 100644
index 0000000000..37676c2c63
--- /dev/null
+++ b/railties/doc/apache_protection
@@ -0,0 +1,3 @@
+Order Deny,Allow
+Deny from all
+Allow from 127.0.0.1 \ No newline at end of file
diff --git a/railties/doc/index.html b/railties/doc/index.html
new file mode 100644
index 0000000000..57e25b75fa
--- /dev/null
+++ b/railties/doc/index.html
@@ -0,0 +1,94 @@
+<html>
+<head>
+ <title>Rails: Welcome on board</title>
+ <style>
+ body { background-color: #fff; color: #333; }
+
+ body, p, ol, ul, td {
+ font-family: verdana, arial, helvetica, sans-serif;
+ font-size: 12px;
+ line-height: 18px;
+ }
+
+ li {
+ margin-bottom: 7px;
+ }
+
+ pre {
+ background-color: #eee;
+ padding: 10px;
+ font-size: 11px;
+ }
+
+ a { color: #000; }
+ a:visited { color: #666; }
+ a:hover { color: #fff; background-color:#000; }
+ </style>
+</head>
+<body>
+
+<h1>Congratulations, you're on Rails!</h1>
+
+<p>
+ <i>You've succesfully configured your web server to point at this Rails application.</i>
+</p>
+
+<p>Before you move on, verify that the following conditions have been met:</p>
+
+<ol>
+ <li>The log directory and the empty log files must be writable to the web server (<code>chmod -R 777 log</code>).
+ <li>
+ The shebang line in the public/dispatch* files must reference your Ruby installation. <br/>
+ You might need to change it to <code>#!/usr/bin/env ruby</code> or point directly at the installation.
+ </li>
+ <li>
+ Rails on Apache needs to have the cgi handler and mod_rewrite enabled. <br/>
+ Somewhere in your httpd.conf, you should have:<br/>
+ <code>AddHandler cgi-script .cgi</code><br/>
+ <code>LoadModule rewrite_module libexec/httpd/mod_rewrite.so</code><br/>
+ <code>AddModule mod_rewrite.c</code>
+ </li>
+</ol>
+
+<p>Take the following steps to get started:</p>
+
+<ol>
+ <li>Create empty production and test databases for your application.<br/>
+ <small>Warning: Don't point your test database at your production database, it'll destroy the latter on test runs!</small>
+ <li>Edit config/database.yml with your database settings.
+ <li>Create a new controller using the <code>script/new_controller</code> generator <br/>
+ <small>Help: Run with no arguments for documentation</small>
+ <li>Create a new model using the <code>script/new_model</code> generator <br/>
+ <small>Help: Run with no arguments for documentation</small>
+ <li>See all the tests run and fail by running <code>rake</code>.
+ <li>Develop your Rails application!
+ <li>Setup FastCGI or mod_ruby to get production-level performance
+</ol>
+
+<p>
+ Having problems getting up and running? First try debugging it yourself by looking at the log files. <br/> Then try the friendly Rails
+ community on IRC (<a href="http://www.rubyonrails.org/show/IRC">howto IRC</a>). It's on FreeNET in channel #rubyonrails.
+</p>
+
+<div style="float: left; margin-right: 20px">
+ <h2>Rails Online</h2>
+
+ <ul>
+ <li><a href="http://www.rubyonrails.org">Ruby on Rails</a></li>
+ <li><a href="http://activerecord.rubyonrails.org">Active Record</a></li>
+ <li><a href="http://actionpack.rubyonrails.org">Action Pack</a></li>
+ </ul>
+</div>
+
+<div style="float: left">
+ <h2>Beyond CGI</h2>
+
+ <ul>
+ <li><a href="http://www.fastcgi.com">FastCGI</a></li>
+ <li><a href="http://raa.ruby-lang.org/list.rhtml?name=fcgi">FastCGI bindings for Ruby</a></li>
+ <li><a href="http://modruby.net/en/">mod_ruby</a></li>
+ </ul>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/railties/environments/development.rb b/railties/environments/development.rb
new file mode 100644
index 0000000000..81d5a73403
--- /dev/null
+++ b/railties/environments/development.rb
@@ -0,0 +1,2 @@
+ActiveRecord::Base.logger = ActionController::Base.logger = ActionMailer::Base.logger = Logger.new("#{RAILS_ROOT}/log/development.log")
+ActiveRecord::Base.establish_connection(:development) \ No newline at end of file
diff --git a/railties/environments/production.rb b/railties/environments/production.rb
new file mode 100644
index 0000000000..1ecda598de
--- /dev/null
+++ b/railties/environments/production.rb
@@ -0,0 +1,6 @@
+ActiveRecord::Base.logger = ActionController::Base.logger = ActionMailer::Base.logger = Logger.new("#{RAILS_ROOT}/log/production.log")
+ActiveRecord::Base.establish_connection(:production)
+
+ActionController::Base.consider_all_requests_local = false
+ActionController::Base.reload_dependencies = false
+ActiveRecord::Base.reload_associations = false \ No newline at end of file
diff --git a/railties/environments/shared.rb b/railties/environments/shared.rb
new file mode 100644
index 0000000000..f5d4771db6
--- /dev/null
+++ b/railties/environments/shared.rb
@@ -0,0 +1,35 @@
+RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + "/../")
+RAILS_ENV = ENV['RAILS_ENV'] || 'development'
+
+ADDITIONAL_LOAD_PATHS = [
+ "app/models",
+ "app/controllers",
+ "app/helpers",
+ "app",
+ "config",
+ "lib",
+ "vendor",
+ "vendor/railties",
+ "vendor/railties/lib",
+ "vendor/activerecord/lib",
+ "vendor/actionpack/lib",
+ "vendor/actionmailer/lib",
+]
+
+ADDITIONAL_LOAD_PATHS.unshift(Dir["#{RAILS_ROOT}/app/models/[a-z]*"].collect{ |dir| "app/models/#{File.basename(dir)}" })
+ADDITIONAL_LOAD_PATHS.unshift("test/mocks/#{RAILS_ENV}")
+
+ADDITIONAL_LOAD_PATHS.flatten.each { |dir| $: << "#{RAILS_ROOT}/#{dir}" }
+
+
+require 'active_record'
+require 'action_controller'
+require 'action_mailer'
+
+require 'yaml'
+
+ActionController::Base.template_root = ActionMailer::Base.template_root = "#{RAILS_ROOT}/app/views/"
+ActiveRecord::Base.configurations = YAML::load(File.open("#{RAILS_ROOT}/config/database.yml"))
+
+ActionController::Base.require_or_load 'abstract_application'
+ActionController::Base.require_or_load "environments/#{RAILS_ENV}" \ No newline at end of file
diff --git a/railties/environments/shared_for_gem.rb b/railties/environments/shared_for_gem.rb
new file mode 100644
index 0000000000..1ae6746122
--- /dev/null
+++ b/railties/environments/shared_for_gem.rb
@@ -0,0 +1,23 @@
+RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + "/../")
+RAILS_ENV = ENV['RAILS_ENV'] || 'development'
+
+ADDITIONAL_LOAD_PATHS = [ "app/models", "app/controllers", "app/helpers", "config", "lib", "vendor" ]
+ADDITIONAL_LOAD_PATHS.unshift(Dir["#{RAILS_ROOT}/app/models/[a-z]*"].collect{ |dir| "app/models/#{File.basename(dir)}" })
+ADDITIONAL_LOAD_PATHS.unshift("test/mocks/#{RAILS_ENV}")
+
+ADDITIONAL_LOAD_PATHS.flatten.each { |dir| $:.unshift "#{RAILS_ROOT}/#{dir}" }
+
+require 'rubygems'
+
+require_gem 'activerecord'
+require_gem 'actionpack'
+require_gem 'actionmailer'
+require_gem 'rails'
+
+require 'yaml'
+
+ActionController::Base.template_root = ActionMailer::Base.template_root = "#{RAILS_ROOT}/app/views/"
+ActiveRecord::Base.configurations = YAML::load(File.open("#{RAILS_ROOT}/config/database.yml"))
+
+ActionController::Base.require_or_load 'abstract_application'
+ActionController::Base.require_or_load "environments/#{RAILS_ENV}"
diff --git a/railties/environments/test.rb b/railties/environments/test.rb
new file mode 100644
index 0000000000..6ab6a1f50a
--- /dev/null
+++ b/railties/environments/test.rb
@@ -0,0 +1,2 @@
+ActiveRecord::Base.logger = ActionController::Base.logger = ActionMailer::Base.logger = Logger.new("#{RAILS_ROOT}/log/test.log")
+ActiveRecord::Base.establish_connection(:test)
diff --git a/railties/fresh_rakefile b/railties/fresh_rakefile
new file mode 100755
index 0000000000..3b746a49a5
--- /dev/null
+++ b/railties/fresh_rakefile
@@ -0,0 +1,104 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+$VERBOSE = nil
+
+require File.dirname(__FILE__) + '/config/environment'
+require 'code_statistics'
+
+desc "Run all the tests on a fresh test database"
+task :default => [ :clone_development_structure_to_test, :test_units, :test_functional ]
+
+desc "Generate API documentatio, show coding stats"
+task :doc => [ :appdoc, :stats ]
+
+
+desc "Run the unit tests in test/unit"
+Rake::TestTask.new("test_units") { |t|
+ t.libs << "test"
+ t.pattern = 'test/unit/*_test.rb'
+ t.verbose = true
+}
+
+desc "Run the functional tests in test/functional"
+Rake::TestTask.new("test_functional") { |t|
+ t.libs << "test"
+ t.pattern = 'test/functional/*_test.rb'
+ t.verbose = true
+}
+
+desc "Generate documentation for the application"
+Rake::RDocTask.new("appdoc") { |rdoc|
+ rdoc.rdoc_dir = 'doc/app'
+ rdoc.title = "Rails Application Documentation"
+ rdoc.options << '--line-numbers --inline-source'
+ rdoc.rdoc_files.include('doc/README_FOR_APP')
+ rdoc.rdoc_files.include('app/**/*.rb')
+}
+
+desc "Generate documentation for the Rails framework"
+Rake::RDocTask.new("apidoc") { |rdoc|
+ rdoc.rdoc_dir = 'doc/api'
+ rdoc.title = "Rails Framework Documentation"
+ rdoc.options << '--line-numbers --inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('vendor/railties/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/railties/MIT-LICENSE')
+ rdoc.rdoc_files.include('vendor/activerecord/README')
+ rdoc.rdoc_files.include('vendor/activerecord/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/activerecord/lib/active_record/**/*.rb')
+ rdoc.rdoc_files.exclude('vendor/activerecord/lib/active_record/vendor/*')
+ rdoc.rdoc_files.include('vendor/actionpack/README')
+ rdoc.rdoc_files.include('vendor/actionpack/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/actionpack/lib/action_controller/**/*.rb')
+ rdoc.rdoc_files.include('vendor/actionpack/lib/action_view/**/*.rb')
+ rdoc.rdoc_files.include('vendor/actionmailer/README')
+ rdoc.rdoc_files.include('vendor/actionmailer/CHANGELOG')
+ rdoc.rdoc_files.include('vendor/actionmailer/lib/action_mailer/base.rb')
+}
+
+desc "Report code statistics (KLOCs, etc) from the application"
+task :stats do
+ CodeStatistics.new(
+ ["Controllers", "app/controllers"],
+ ["Helpers", "app/helpers"],
+ ["Models", "app/models"],
+ ["Units", "test/unit"],
+ ["Functionals", "test/functional"]
+ ).to_s
+end
+
+desc "Recreate the test databases from the development structure"
+task :clone_development_structure_to_test => [ :db_structure_dump, :purge_test_database ] do
+ if ActiveRecord::Base.configurations["test"]["adapter"] == "mysql"
+ ActiveRecord::Base.establish_connection(:test)
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
+ IO.readlines("db/development_structure.sql").join.split("\n\n").each do |table|
+ ActiveRecord::Base.connection.execute(table)
+ end
+ elsif ActiveRecord::Base.configurations["test"]["adapter"] == "postgresql"
+ `psql -U #{ActiveRecord::Base.configurations["test"]["username"]} -f db/development_structure.sql #{ActiveRecord::Base.configurations["test"]["database"]}`
+ end
+end
+
+desc "Dump the database structure to a SQL file"
+task :db_structure_dump do
+ if ActiveRecord::Base.configurations["test"]["adapter"] == "mysql"
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations["test"])
+ File.open("db/development_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
+ elsif ActiveRecord::Base.configurations["test"]["adapter"] == "postgresql"
+ `pg_dump -U #{ActiveRecord::Base.configurations["test"]["username"]} -s -f db/development_structure.sql #{ActiveRecord::Base.configurations["test"]["database"]}`
+ end
+end
+
+desc "Drop the test database and bring it back again"
+task :purge_test_database do
+ if ActiveRecord::Base.configurations["test"]["adapter"] == "mysql"
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations["development"])
+ ActiveRecord::Base.connection.recreate_database(ActiveRecord::Base.configurations["test"]["database"])
+ elsif ActiveRecord::Base.configurations["test"]["adapter"] == "postgresql"
+ `dropdb -U #{ActiveRecord::Base.configurations["test"]["username"]} #{ActiveRecord::Base.configurations["test"]["database"]}`
+ `createdb -U #{ActiveRecord::Base.configurations["test"]["username"]} #{ActiveRecord::Base.configurations["test"]["database"]}`
+ end
+end
diff --git a/railties/generators/new_controller.rb b/railties/generators/new_controller.rb
new file mode 100755
index 0000000000..3060c06382
--- /dev/null
+++ b/railties/generators/new_controller.rb
@@ -0,0 +1,43 @@
+#!/usr/local/bin/ruby
+require File.dirname(__FILE__) + '/../config/environment'
+require 'generator'
+
+unless ARGV.empty?
+ rails_root = File.dirname(__FILE__) + '/..'
+ name = ARGV.shift
+ actions = ARGV
+ Generator::Controller.new(rails_root, name, actions).generate
+else
+ puts <<-END_HELP
+
+NAME
+ new_controller - create controller and view stub files
+
+SYNOPSIS
+ new_controller ControllerName action [action ...]
+
+DESCRIPTION
+ The new_controller generator takes the name of the new controller as the
+ first argument and a variable number of view names as subsequent arguments.
+ The controller name should be supplied without a "Controller" suffix. The
+ generator will add that itself.
+
+ From the passed arguments, new_controller generates a controller file in
+ app/controllers with a render action for each of the view names passed.
+ It then creates a controller test suite in test/functional with one failing
+ test case. Finally, it creates an HTML stub for each of the view names in
+ app/views under a directory with the same name as the controller.
+
+EXAMPLE
+ new_controller Blog list display new edit
+
+ This will generate a BlogController class in
+ app/controllers/blog_controller.rb, a BlogHelper class in
+ app/helpers/blog_helper.rb and a BlogControllerTest in
+ test/functional/blog_controller_test.rb. It will also create list.rhtml,
+ display.rhtml, new.rhtml, and edit.rhtml in app/views/blog.
+
+ The BlogController class will have the following methods: list, display, new, edit.
+ Each will default to render the associated template file.
+END_HELP
+end
diff --git a/railties/generators/new_crud.rb b/railties/generators/new_crud.rb
new file mode 100755
index 0000000000..4eaa1cb1f3
--- /dev/null
+++ b/railties/generators/new_crud.rb
@@ -0,0 +1,34 @@
+#!/usr/local/bin/ruby
+require File.dirname(__FILE__) + '/../config/environment'
+require 'generator'
+
+unless ARGV.empty?
+ rails_root = File.dirname(__FILE__) + '/..'
+ name = ARGV.shift
+ actions = ARGV
+ Generator::Model.new(rails_root, name).generate
+ Generator::Controller.new(rails_root, name, actions, :scaffold => true).generate
+else
+ puts <<-END_HELP
+
+NAME
+ new_crud - create a model and a controller scaffold
+
+SYNOPSIS
+ new_crud ModelName [action ...]
+
+DESCRIPTION
+ The new_crud generator takes the name of the new model as the
+ first argument and an optional list of controller actions as the
+ subsequent arguments. All actions may be omitted since the controller
+ will have scaffolding automatically set up for this model.
+
+EXAMPLE
+ new_crud Account
+
+ This will generate an Account model and controller with scaffolding.
+ Now create the accounts table in your database and browse to
+ http://localhost/account/ -- voila, you're on Rails!
+
+END_HELP
+end
diff --git a/railties/generators/new_mailer.rb b/railties/generators/new_mailer.rb
new file mode 100644
index 0000000000..05d0c9ae82
--- /dev/null
+++ b/railties/generators/new_mailer.rb
@@ -0,0 +1,43 @@
+#!/usr/local/bin/ruby
+require File.dirname(__FILE__) + '/../config/environment'
+require 'generator'
+
+unless ARGV.empty?
+ rails_root = File.dirname(__FILE__) + '/..'
+ name = ARGV.shift
+ actions = ARGV
+ Generator::Mailer.new(rails_root, name, actions).generate
+else
+ puts <<-END_HELP
+
+NAME
+ new_mailer - create mailer and view stub files
+
+SYNOPSIS
+ new_mailer MailerName action [action ...]
+
+DESCRIPTION
+ The new_mailer generator takes the name of the new mailer class as the
+ first argument and a variable number of mail action names as subsequent
+ arguments.
+
+ From the passed arguments, new_mailer generates a class file in
+ app/models with a mail action for each of the mail action names passed.
+ It then creates a mail test suite in test/unit with one stub test case
+ and one stub fixture per mail action. Finally, it creates a template stub
+ for each of the mail action names in app/views under a directory with the
+ same name as the class.
+
+EXAMPLE
+ new_mailer Notifications signup forgot_password invoice
+
+ This will generate a Notifications class in
+ app/models/notifications.rb, a NotificationsTest in
+ test/unit/notifications_test.rb, and signup, forgot_password, and invoice
+ in test/fixture/notification. It will also create signup.rhtml,
+ forgot_password.rhtml, and invoice.rhtml in app/views/notifications.
+
+ The Notifications class will have the following methods: signup,
+ forgot_password, and invoice.
+END_HELP
+end
diff --git a/railties/generators/new_model.rb b/railties/generators/new_model.rb
new file mode 100755
index 0000000000..f6fbf5f002
--- /dev/null
+++ b/railties/generators/new_model.rb
@@ -0,0 +1,31 @@
+#!/usr/local/bin/ruby
+require File.dirname(__FILE__) + '/../config/environment'
+require 'generator'
+
+if ARGV.size == 1
+ rails_root = File.dirname(__FILE__) + '/..'
+ name = ARGV.shift
+ Generator::Model.new(rails_root, name).generate
+else
+ puts <<-HELP
+
+NAME
+ new_model - create model stub files
+
+SYNOPSIS
+ new_model ModelName
+
+DESCRIPTION
+ The new_model generator takes a model name (in CamelCase) and generates
+ a new, empty model in app/models, a test suite in test/unit with one
+ failing test case, and a fixtures directory in test/fixtures.
+
+EXAMPLE
+ new_model Account
+
+ This will generate an Account class in app/models/account.rb, an
+ AccountTest in test/unit/account_test.rb, and the directory
+ test/fixtures/account.
+
+HELP
+end
diff --git a/railties/generators/templates/controller.erb b/railties/generators/templates/controller.erb
new file mode 100644
index 0000000000..600f5d2c59
--- /dev/null
+++ b/railties/generators/templates/controller.erb
@@ -0,0 +1,19 @@
+class <%= class_name %>Controller < AbstractApplicationController
+ helper :<%= file_name %>
+<% if options[:scaffold] -%>
+ model :<%= file_name %>
+ scaffold :<%= options[:scaffold] %>
+
+ <%- for action in actions -%>
+ #def <%= action %>
+ #end
+
+ <%- end -%>
+<% else -%>
+ <%- for action in actions -%>
+ def <%= action %>
+ end
+
+ <%- end -%>
+<% end -%>
+end
diff --git a/railties/generators/templates/controller_test.erb b/railties/generators/templates/controller_test.erb
new file mode 100644
index 0000000000..5577379c62
--- /dev/null
+++ b/railties/generators/templates/controller_test.erb
@@ -0,0 +1,17 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require '<%= file_name %>_controller'
+
+# Re-raise errors caught by the controller.
+class <%= class_name %>Controller; def rescue_action(e) raise e end; end
+
+class <%= class_name %>ControllerTest < Test::Unit::TestCase
+ def setup
+ @controller = <%= class_name %>Controller.new
+ @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
+ end
+
+ # Replace this with your real tests
+ def test_truth
+ assert true
+ end
+end
diff --git a/railties/generators/templates/controller_view.rhtml b/railties/generators/templates/controller_view.rhtml
new file mode 100644
index 0000000000..d8a310df50
--- /dev/null
+++ b/railties/generators/templates/controller_view.rhtml
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><%= class_name %>#<%= action %></title>
+</head>
+<body>
+<h1><%= class_name %>#<%= action %></h1>
+<p>Find me in app/views/<%= file_name %>/<%= action %>.rhtml</p>
+</body>
+</html>
diff --git a/railties/generators/templates/helper.erb b/railties/generators/templates/helper.erb
new file mode 100644
index 0000000000..3fe2ecdc74
--- /dev/null
+++ b/railties/generators/templates/helper.erb
@@ -0,0 +1,2 @@
+module <%= class_name %>Helper
+end
diff --git a/railties/generators/templates/mailer.erb b/railties/generators/templates/mailer.erb
new file mode 100644
index 0000000000..5afc254923
--- /dev/null
+++ b/railties/generators/templates/mailer.erb
@@ -0,0 +1,15 @@
+require 'action_mailer'
+
+class <%= class_name %> < ActionMailer::Base
+
+<% for action in actions -%>
+ def <%= action %>(sent_on = Time.now)
+ @recipients = ''
+ @from = ''
+ @subject = ''
+ @body = {}
+ @sent_on = sent_on
+ end
+
+<% end -%>
+end
diff --git a/railties/generators/templates/mailer_action.rhtml b/railties/generators/templates/mailer_action.rhtml
new file mode 100644
index 0000000000..b481906829
--- /dev/null
+++ b/railties/generators/templates/mailer_action.rhtml
@@ -0,0 +1,3 @@
+<%= class_name %>#<%= action %>
+
+Find me in app/views/<%= file_name %>/<%= action %>.rhtml
diff --git a/railties/generators/templates/mailer_fixture.rhtml b/railties/generators/templates/mailer_fixture.rhtml
new file mode 100644
index 0000000000..f315d430ed
--- /dev/null
+++ b/railties/generators/templates/mailer_fixture.rhtml
@@ -0,0 +1,4 @@
+<%= class_name %>#<%= action %>
+
+Find me in test/fixtures/<%= file_name %>/<%= action %>.
+I'm tested against the view in app/views/<%= file_name %>/<%= action %>.
diff --git a/railties/generators/templates/mailer_test.erb b/railties/generators/templates/mailer_test.erb
new file mode 100644
index 0000000000..f17d614195
--- /dev/null
+++ b/railties/generators/templates/mailer_test.erb
@@ -0,0 +1,37 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require '<%= file_name %>'
+
+class <%= class_name %>Test < Test::Unit::TestCase
+ FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
+
+ def setup
+ ActionMailer::Base.delivery_method = :test
+ ActionMailer::Base.perform_deliveries = true
+ ActionMailer::Base.deliveries = []
+
+ @expected = TMail::Mail.new
+ @expected.to = 'test@localhost'
+ @expected.from = 'test@localhost'
+ @expected.subject = '<%= class_name %> test mail'
+ end
+
+<% for action in actions -%>
+ def test_<%= action %>
+ @expected.body = read_fixture('<%= action %>')
+ @expected.date = Time.now
+
+ created = nil
+ assert_nothing_raised { created = <%= class_name %>.create_<%= action %>(@expected.date) }
+ assert_not_nil created
+ assert_equal @expected.encoded, created.encoded
+
+ assert_nothing_raised { <%= class_name %>.deliver_<%= action %>(@expected.date) }
+ assert_equal @expected.encoded, ActionMailer::Base.deliveries.first.encoded
+ end
+
+<% end -%>
+ private
+ def read_fixture(action)
+ IO.readlines("#{FIXTURES_PATH}/<%= file_name %>/#{action}")
+ end
+end
diff --git a/railties/generators/templates/model.erb b/railties/generators/templates/model.erb
new file mode 100644
index 0000000000..8d4c89e912
--- /dev/null
+++ b/railties/generators/templates/model.erb
@@ -0,0 +1,2 @@
+class <%= class_name %> < ActiveRecord::Base
+end
diff --git a/railties/generators/templates/model_test.erb b/railties/generators/templates/model_test.erb
new file mode 100644
index 0000000000..a3ad2b72fb
--- /dev/null
+++ b/railties/generators/templates/model_test.erb
@@ -0,0 +1,11 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require '<%= file_name %>'
+
+class <%= class_name %>Test < Test::Unit::TestCase
+ fixtures :<%= table_name %>
+
+ # Replace this with your real tests
+ def test_truth
+ assert true
+ end
+end \ No newline at end of file
diff --git a/railties/helpers/abstract_application.rb b/railties/helpers/abstract_application.rb
new file mode 100644
index 0000000000..fa26cd0399
--- /dev/null
+++ b/railties/helpers/abstract_application.rb
@@ -0,0 +1,5 @@
+# The filters added to this controller will be run for all controllers in the application.
+# Likewise will all the methods added be available for all controllers.
+class AbstractApplicationController < ActionController::Base
+ helper :application
+end \ No newline at end of file
diff --git a/railties/helpers/application_helper.rb b/railties/helpers/application_helper.rb
new file mode 100644
index 0000000000..0392b53b46
--- /dev/null
+++ b/railties/helpers/application_helper.rb
@@ -0,0 +1,3 @@
+# The methods added to this helper will be available to all templates in the application.
+module ApplicationHelper
+end
diff --git a/railties/helpers/test_helper.rb b/railties/helpers/test_helper.rb
new file mode 100644
index 0000000000..d348f26517
--- /dev/null
+++ b/railties/helpers/test_helper.rb
@@ -0,0 +1,16 @@
+ENV["RAILS_ENV"] ||= "test"
+require File.dirname(__FILE__) + "/../config/environment"
+
+require 'test/unit'
+require 'active_record/fixtures'
+require 'action_controller/test_process'
+
+# Make rubygems available for testing if possible
+begin require('rubygems'); rescue LoadError; end
+begin require('dev-utils/debug'); rescue LoadError; end
+
+def create_fixtures(*table_names)
+ Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
+end
+
+Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/" \ No newline at end of file
diff --git a/railties/html/404.html b/railties/html/404.html
new file mode 100644
index 0000000000..edbc89bf99
--- /dev/null
+++ b/railties/html/404.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+ <h1>File not found</h1>
+ <p>Change this error message for pages not found in public/404.html</p>
+</body>
+</html> \ No newline at end of file
diff --git a/railties/html/500.html b/railties/html/500.html
new file mode 100644
index 0000000000..ee0c919c4a
--- /dev/null
+++ b/railties/html/500.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+ <h1>Application error (Apache)</h1>
+ <p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p>
+</body>
+</html> \ No newline at end of file
diff --git a/railties/html/index.html b/railties/html/index.html
new file mode 100644
index 0000000000..4949c64a5a
--- /dev/null
+++ b/railties/html/index.html
@@ -0,0 +1 @@
+<html><head><META HTTP-EQUIV="Refresh" CONTENT="0;URL=_doc/index.html"></head></html> \ No newline at end of file
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
diff --git a/railties/test/webrick_dispatcher_test.rb b/railties/test/webrick_dispatcher_test.rb
new file mode 100644
index 0000000000..2c6b51ae62
--- /dev/null
+++ b/railties/test/webrick_dispatcher_test.rb
@@ -0,0 +1,30 @@
+#!/bin/env ruby
+
+$:.unshift(File.dirname(__FILE__) + "/../lib")
+
+require 'test/unit'
+require 'webrick_server'
+
+class ParseUriTest < Test::Unit::TestCase
+
+ def test_parse_uri_old_behavior
+ assert_equal [true, 'forum', 'index', '1'], DispatchServlet.parse_uri('/forum/index/1')
+ assert_equal [true, 'forum', 'index', nil], DispatchServlet.parse_uri('/forum/index')
+ assert_equal [true, 'forum', 'index', nil], DispatchServlet.parse_uri('/forum/')
+ end
+
+ def test_parse_uri_new_behavior
+ assert_equal [true, 'forum', 'index', '1'], DispatchServlet.parse_uri('/forum/index/1/')
+ assert_equal [true, 'forum', 'index', nil], DispatchServlet.parse_uri('/forum/index/')
+ assert_equal [true, 'forum', 'index', nil], DispatchServlet.parse_uri('/forum')
+ end
+
+ def test_parse_uri_failures
+ assert_equal [false, nil, nil, nil], DispatchServlet.parse_uri('/')
+ assert_equal [false, nil, nil, nil], DispatchServlet.parse_uri('a')
+ assert_equal [false, nil, nil, nil], DispatchServlet.parse_uri('/forum//')
+ assert_equal [false, nil, nil, nil], DispatchServlet.parse_uri('/+forum/')
+ assert_equal [false, nil, nil, nil], DispatchServlet.parse_uri('forum/')
+ end
+
+end