From 06860dcf29d73c0c4fbe5a42fde4db0ce9753937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 4 Feb 2010 14:14:11 +0100 Subject: Remove duplicated version check. --- railties/lib/rails/commands.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 4240038673..55744db275 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -60,8 +60,6 @@ when 'runner' require ENV_PATH -when '--version', '-v' - puts "Rails #{Rails::VERSION::STRING}" when '--help', '-h' puts HELP_TEXT when '--version', '-v' -- cgit v1.2.3 From 25b6b95459ae71218754e8469f77f86b676bf215 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Thu, 4 Feb 2010 17:00:50 +0000 Subject: Make RAILS_* give deprecation warning just once --- railties/lib/rails/deprecation.rb | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/railties/lib/rails/deprecation.rb b/railties/lib/rails/deprecation.rb index f28da5a6b0..1eb6d804b6 100644 --- a/railties/lib/rails/deprecation.rb +++ b/railties/lib/rails/deprecation.rb @@ -2,6 +2,9 @@ require "active_support/string_inquirer" require "active_support/deprecation" RAILS_ROOT = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do + cattr_accessor :warned + self.warned = false + def target Rails.root end @@ -11,12 +14,17 @@ RAILS_ROOT = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do end def warn(callstack, called, args) - msg = "RAILS_ROOT is deprecated! Use Rails.root instead" - ActiveSupport::Deprecation.warn(msg, callstack) + unless warned + ActiveSupport::Deprecation.warn("RAILS_ROOT is deprecated! Use Rails.root instead", callstack) + self.warned = true + end end end).new RAILS_ENV = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do + cattr_accessor :warned + self.warned = false + def target Rails.env end @@ -26,12 +34,17 @@ RAILS_ENV = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do end def warn(callstack, called, args) - msg = "RAILS_ENV is deprecated! Use Rails.env instead" - ActiveSupport::Deprecation.warn(msg, callstack) + unless warned + ActiveSupport::Deprecation.warn("RAILS_ENV is deprecated! Use Rails.env instead", callstack) + self.warned = true + end end end).new RAILS_DEFAULT_LOGGER = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do + cattr_accessor :warned + self.warned = false + def target Rails.logger end @@ -41,7 +54,9 @@ RAILS_DEFAULT_LOGGER = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) end def warn(callstack, called, args) - msg = "RAILS_DEFAULT_LOGGER is deprecated! Use Rails.logger instead" - ActiveSupport::Deprecation.warn(msg, callstack) + unless warned + ActiveSupport::Deprecation.warn("RAILS_DEFAULT_LOGGER is deprecated! Use Rails.logger instead", callstack) + self.warned = true + end end end).new -- cgit v1.2.3 From 6b3fb384615003ae6cf74e8acfdb8bea9c0f683d Mon Sep 17 00:00:00 2001 From: Antonio Cangiano Date: Thu, 4 Feb 2010 12:21:27 -0500 Subject: Updated the database.yml file generated for ibm_db to the latest version of DB2 and the gem. [#3852 state:committed] Signed-off-by: Jeremy Kemper --- .../app/templates/config/databases/ibm_db.yml | 31 ++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml index 2cecb5c879..2784a949fb 100644 --- a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml @@ -4,23 +4,32 @@ # http://rubyforge.org/projects/rubyibm/ # # To install the ibm_db gem: +# # On Linux: -# Source the db2profile file and set the necessary environment variables: +# . /home/db2inst1/sqllib/db2profile +# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include +# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib32 +# gem install ibm_db # +# On Mac OS X 10.5: # . /home/db2inst1/sqllib/db2profile -# export IBM_DB_DIR=/opt/ibm/db2/V9.1 -# export IBM_DB_LIB=/opt/ibm/db2/V9.1/lib32 +# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include +# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib32 +# export ARCHFLAGS="-arch i386" +# gem install ibm_db # -# Then issue the command: gem install ibm_db +# On Mac OS X 10.6: +# . /home/db2inst1/sqllib/db2profile +# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include +# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib64 +# export ARCHFLAGS="-arch x86_64" +# gem install ibm_db # # On Windows: -# Issue the command: gem install ibm_db -# If prompted, select the mswin32 option -# -# For more details on the installation refer to http://rubyforge.org/docman/view.php/2361/7682/IBM_DB_GEM.pdf +# Issue the command: gem install ibm_db # -# For more details on the connection parameters below refer to: -# http://rubyibm.rubyforge.org/docs/adapter/0.9.0/rdoc/classes/ActiveRecord/ConnectionAdapters/IBM_DBAdapter.html +# For more details on the installation and the connection parameters below, +# please refer to the latest documents at http://rubyforge.org/docman/?group_id=2361 development: adapter: ibm_db @@ -52,7 +61,7 @@ production: adapter: ibm_db username: db2inst1 password: - database: <%= app_name[0,4] %>_prd + database: <%= app_name[0,8] %> #schema: db2inst1 #host: localhost #port: 50000 -- cgit v1.2.3 From 5c07c33ab4de037aeb1f6cc6817fddd28f9a35d2 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 09:28:41 -0800 Subject: Move framework requires and Bundler.require from boot.rb to app.rb. Cut down the list of railtie choices to those that make sense. --- .../rails/app/templates/config/application.rb | 14 +++++++++++ .../generators/rails/app/templates/config/boot.rb | 29 ---------------------- railties/test/generators/app_generator_test.rb | 2 +- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/config/application.rb b/railties/lib/generators/rails/app/templates/config/application.rb index 78a355d2f4..2872d187ba 100644 --- a/railties/lib/generators/rails/app/templates/config/application.rb +++ b/railties/lib/generators/rails/app/templates/config/application.rb @@ -1,5 +1,19 @@ require File.expand_path('../boot', __FILE__) +<% unless options[:skip_activerecord] -%> +require 'rails/all' +<% else -%> +# Pick the frameworks you want: +# require "active_record/railtie" +require "action_controller/railtie" +require "action_mailer/railtie" +require "active_resource/railtie" +require "rails/test_unit/railtie" +<% end -%> + +# Auto-require all bundled libraries. +Bundler.require + module <%= app_const_base %> class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. diff --git a/railties/lib/generators/rails/app/templates/config/boot.rb b/railties/lib/generators/rails/app/templates/config/boot.rb index 03396113e8..29c9d506e5 100644 --- a/railties/lib/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/generators/rails/app/templates/config/boot.rb @@ -15,32 +15,3 @@ rescue LoadError # # require 'rubygems' end - -# Auto-require all bundled libraries. -Bundler.require - -<% unless options[:skip_activerecord] -%> -require 'rails/all' - -# To pick the frameworks you want, remove 'require "rails/all"' -# and list the framework railties that you want: -# -# require "active_support/railtie" -# require "active_model/railtie" -# require "active_record/railtie" -# require "action_controller/railtie" -# require "action_view/railtie" -# require "action_mailer/railtie" -# require "active_resource/railtie" -# require "rails/test_unit/railtie" -<% else -%> -# Pick the frameworks you want: -# require "active_model/railtie" -# require "active_record/railtie" -require "active_support/railtie" -require "action_controller/railtie" -require "action_view/railtie" -require "action_mailer/railtie" -require "active_resource/railtie" -require "rails/test_unit/railtie" -<% end -%> diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 76579adb26..9c70dcbc92 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -90,7 +90,7 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_activerecord_is_removed_from_frameworks_if_skip_activerecord_is_given run_generator [destination_root, "--skip-activerecord"] - assert_file "config/boot.rb", /# require "active_record\/railtie"/ + assert_file "config/application.rb", /# require "active_record\/railtie"/ end def test_prototype_and_test_unit_are_added_by_default -- cgit v1.2.3 From 23ad1eff0dab4079b7bc68f71df537fc85582d05 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 09:29:18 -0800 Subject: Rationalize railtie dependencies: AC uses AV; AR uses AMo; and Rails always uses AS. --- actionmailer/lib/action_mailer/railtie.rb | 2 +- actionpack/lib/action_controller/railtie.rb | 1 + activerecord/lib/active_record/railtie.rb | 6 ++++-- railties/lib/rails/all.rb | 5 +---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 4ed70503fd..b5230f14ed 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -22,4 +22,4 @@ module ActionMailer ActionMailer::Base.send(:include, ActionController::UrlFor) if defined?(ActionController) end end -end \ No newline at end of file +end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 9151de4462..55a5c22ac0 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -1,5 +1,6 @@ require "action_controller" require "rails" +require "action_view/railtie" module ActionController class Railtie < Rails::Railtie diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 2b204043b4..e70b0d1bfb 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -1,10 +1,12 @@ +require "active_record" +require "rails" +require "active_model/railtie" + # For now, action_controller must always be present with # rails, so let's make sure that it gets required before # here. This is needed for correctly setting up the middleware. # In the future, this might become an optional require. -require "active_record" require "action_controller/railtie" -require "rails" module ActiveRecord class Railtie < Rails::Railtie diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb index 1a0b4a8d73..82775b7e3b 100644 --- a/railties/lib/rails/all.rb +++ b/railties/lib/rails/all.rb @@ -1,11 +1,8 @@ require "rails" %w( - active_support - active_model active_record action_controller - action_view action_mailer active_resource rails/test_unit @@ -14,4 +11,4 @@ require "rails" require "#{framework}/railtie" rescue LoadError end -end \ No newline at end of file +end -- cgit v1.2.3 From 2faf94a7af7326517b45a2c9cff5ee476092e138 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 09:42:28 -0800 Subject: Use the correct environment.rb path --- load_paths.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/load_paths.rb b/load_paths.rb index 55e2a530bd..d5f2ca0734 100644 --- a/load_paths.rb +++ b/load_paths.rb @@ -1,5 +1,5 @@ begin - require File.expand_path('../vendor/environment', __FILE__) + require File.expand_path('../.bundle/environment', __FILE__) rescue LoadError begin require 'rubygems' @@ -18,4 +18,4 @@ rescue LoadError $:.unshift File.expand_path("../#{framework}/lib", __FILE__) end end -end \ No newline at end of file +end -- cgit v1.2.3 From 6154278d22994c4dcdb529d3c19b4f446125ed50 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 09:52:27 -0800 Subject: Fix broken autorequires --- Gemfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 6c2f8a35fe..3310dd5926 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ if RUBY_VERSION < '1.9' end # AR -gem "sqlite3-ruby", ">= 1.2.5" +gem "sqlite3-ruby", ">= 1.2.5", :require => 'sqlite3' group :test do gem "pg", ">= 0.8.0" @@ -19,18 +19,18 @@ group :test do end # AP -gem "rack-test", "0.5.3" +gem "rack-test", "0.5.3", :require => 'rack/test' gem "RedCloth", ">= 4.2.2" if ENV['CI'] gem "nokogiri", ">= 1.4.0" - gem "memcache-client", ">= 1.7.6" + gem "memcache-client", ">= 1.7.6", :require => 'memcache' # fcgi gem doesn't compile on 1.9 # avoid minitest strangeness on 1.9 if RUBY_VERSION < '1.9.0' gem "fcgi", ">= 0.8.7" else - gem "test-unit", ">= 2.0.5" + gem "test-unit", ">= 2.0.5", :require => 'test/unit' end end -- cgit v1.2.3 From 358451c2194c5b89b576fd623811da708ee89d95 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 10:45:35 -0800 Subject: Rails script commands load the application rather than just boot --- railties/lib/generators/rails/app/templates/script/rails | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/generators/rails/app/templates/script/rails b/railties/lib/generators/rails/app/templates/script/rails index 2fcf6d09b5..e99d50f695 100644 --- a/railties/lib/generators/rails/app/templates/script/rails +++ b/railties/lib/generators/rails/app/templates/script/rails @@ -5,5 +5,5 @@ BOOT_PATH = File.expand_path('../../config/boot', __FILE__) APP_PATH = File.expand_path('../../config/application', __FILE__) ROOT_PATH = File.expand_path('../..', __FILE__) -require BOOT_PATH +require APP_PATH require 'rails/commands' -- cgit v1.2.3 From ca273d171c2663317842dba2152ba930f03e8e81 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 10:49:41 -0800 Subject: Revert "Rails script commands load the application rather than just boot" This reverts commit 358451c2194c5b89b576fd623811da708ee89d95. --- railties/lib/generators/rails/app/templates/script/rails | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/generators/rails/app/templates/script/rails b/railties/lib/generators/rails/app/templates/script/rails index e99d50f695..2fcf6d09b5 100644 --- a/railties/lib/generators/rails/app/templates/script/rails +++ b/railties/lib/generators/rails/app/templates/script/rails @@ -5,5 +5,5 @@ BOOT_PATH = File.expand_path('../../config/boot', __FILE__) APP_PATH = File.expand_path('../../config/application', __FILE__) ROOT_PATH = File.expand_path('../..', __FILE__) -require APP_PATH +require BOOT_PATH require 'rails/commands' -- cgit v1.2.3 From 293fd9daf82c99d1dd57528ad0b770fad4cb8ce2 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 10:50:14 -0800 Subject: server command loads the application --- railties/lib/rails/commands.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 55744db275..500dcf7f9e 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -33,6 +33,7 @@ when 'c', 'console' require APP_PATH Rails::Console.start(Rails::Application) when 's', 'server' + require APP_PATH require 'rails/commands/server' Dir.chdir(ROOT_PATH) Rails::Server.start @@ -68,4 +69,4 @@ when '--version', '-v' else puts "Error: Command not recognized" puts HELP_TEXT -end \ No newline at end of file +end -- cgit v1.2.3 From a871b1a4d246dcf6616a5e24e5d4df192428e690 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 10:56:16 -0800 Subject: Depend on bundler >= 0.9.1 --- ci/ci_build.rb | 2 +- rails.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/ci_build.rb b/ci/ci_build.rb index 522d1209c9..e40123e228 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -23,7 +23,7 @@ build_results = {} build_results[:geminstaller] = system "sudo gem install rubygems-update -v 1.3.5 --no-ri --no-rdoc" # Install required version of bundler. -build_results[:geminstaller] = system "sudo gem install bundler -v 0.9.1.pre1 --prerelease --no-ri --no-rdoc" +build_results[:geminstaller] = system "sudo gem install bundler -v 0.9.1 --prerelease --no-ri --no-rdoc" cd root_dir do puts diff --git a/rails.gemspec b/rails.gemspec index fb69baebf4..35874fc633 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -19,5 +19,5 @@ Gem::Specification.new do |s| s.add_dependency('activeresource', '= 3.0.0.beta') s.add_dependency('actionmailer', '= 3.0.0.beta') s.add_dependency('railties', '= 3.0.0.beta') - s.add_dependency('bundler', '>= 0.9.1.pre1') + s.add_dependency('bundler', '>= 0.9.1') end -- cgit v1.2.3 From a74ed0c2eef87d7fd159d9ac294ced33f4b10bfc Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 11:04:50 -0800 Subject: Autorequire default libs and those in groups named after the current Rails environment --- railties/lib/generators/rails/app/templates/config/application.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/config/application.rb b/railties/lib/generators/rails/app/templates/config/application.rb index 2872d187ba..7c555c2542 100644 --- a/railties/lib/generators/rails/app/templates/config/application.rb +++ b/railties/lib/generators/rails/app/templates/config/application.rb @@ -11,8 +11,8 @@ require "active_resource/railtie" require "rails/test_unit/railtie" <% end -%> -# Auto-require all bundled libraries. -Bundler.require +# Auto-require default libraries and those for the current Rails environment. +Bundler.require :default, Rails.env module <%= app_const_base %> class Application < Rails::Application -- cgit v1.2.3 From c697974fad669ce47abe8e30cfed280215810cde Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 11:36:57 -0800 Subject: Bump to bundler 0.9.2 --- ci/ci_build.rb | 2 +- rails.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/ci_build.rb b/ci/ci_build.rb index e40123e228..b70d59fad4 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -23,7 +23,7 @@ build_results = {} build_results[:geminstaller] = system "sudo gem install rubygems-update -v 1.3.5 --no-ri --no-rdoc" # Install required version of bundler. -build_results[:geminstaller] = system "sudo gem install bundler -v 0.9.1 --prerelease --no-ri --no-rdoc" +build_results[:geminstaller] = system "sudo gem install bundler -v 0.9.2 --prerelease --no-ri --no-rdoc" cd root_dir do puts diff --git a/rails.gemspec b/rails.gemspec index 35874fc633..a904d3d08b 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -19,5 +19,5 @@ Gem::Specification.new do |s| s.add_dependency('activeresource', '= 3.0.0.beta') s.add_dependency('actionmailer', '= 3.0.0.beta') s.add_dependency('railties', '= 3.0.0.beta') - s.add_dependency('bundler', '>= 0.9.1') + s.add_dependency('bundler', '>= 0.9.2') end -- cgit v1.2.3 From 203626867934a2772a5a3f096521b56d59273407 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Thu, 4 Feb 2010 01:44:54 -0500 Subject: Link to main Arel repository Signed-off-by: Jeremy Kemper --- railties/guides/source/3_0_release_notes.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/3_0_release_notes.textile b/railties/guides/source/3_0_release_notes.textile index 5e96f8cf06..7679302ff9 100644 --- a/railties/guides/source/3_0_release_notes.textile +++ b/railties/guides/source/3_0_release_notes.textile @@ -8,7 +8,7 @@ Even if you don't give a hoot about any of our internal cleanups, Rails 3.0 is g * Brand new router with an emphasis on RESTful declarations * New Action Mailer API modelled after Action Controller (now without the agonizing pain of sending multipart messages!) -* New Active Record chainable query language built on top of relational algebra +* New Active Record chainable query language built on top of "Arel":http://github.com/brynary/arel, a relational algebra engine * Unobtrusive JavaScript helpers with drivers for Prototype, jQuery, and more coming (end of inline JS) * Explicit dependency management with Bundler @@ -131,7 +131,7 @@ More Information: - "Rails Edge Architecture":http://yehudakatz.com/2009/06/11/r h4. Arel Integration -"Arel":http://github.com/rails/arel (or Active Relation) has been taken on as the underpinnings of Active Record and is now required for Rails. Arel provides an SQL abstraction that simplifies out Active Record and provides the underpinnings for the relation functionality in Active Record. +"Arel":http://github.com/brynary/arel (or Active Relation) has been taken on as the underpinnings of Active Record and is now required for Rails. Arel provides an SQL abstraction that simplifies out Active Record and provides the underpinnings for the relation functionality in Active Record. More information: - "Why I wrote Arel":http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/. -- cgit v1.2.3 From 127e53453dc52e07aff877212e204084f7321529 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 12:22:26 -0800 Subject: Ensure javascripts are pulled in so UJS can hook the Delete link --- railties/lib/generators/erb/scaffold/templates/layout.html.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/railties/lib/generators/erb/scaffold/templates/layout.html.erb b/railties/lib/generators/erb/scaffold/templates/layout.html.erb index 7aa049fe80..496de90ebb 100644 --- a/railties/lib/generators/erb/scaffold/templates/layout.html.erb +++ b/railties/lib/generators/erb/scaffold/templates/layout.html.erb @@ -3,6 +3,7 @@ <%= controller_class_name %>: <%%= controller.action_name %> <%%= stylesheet_link_tag 'scaffold' %> + <%%= javascript_include_tag :defaults %> -- cgit v1.2.3 From 78de17cf7095af8e86d192af8d8fbe21e6f193d9 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 14:15:16 -0800 Subject: Expose CSRF tag for UJS adapters --- actionpack/lib/action_view/helpers.rb | 2 ++ actionpack/lib/action_view/helpers/csrf_helper.rb | 12 ++++++++++++ .../test/controller/request_forgery_protection_test.rb | 16 +++++++++++++++- .../generators/erb/scaffold/templates/layout.html.erb | 1 + 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 actionpack/lib/action_view/helpers/csrf_helper.rb diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb index ceb0e18d80..b4f649385a 100644 --- a/actionpack/lib/action_view/helpers.rb +++ b/actionpack/lib/action_view/helpers.rb @@ -7,6 +7,7 @@ module ActionView #:nodoc: autoload :AtomFeedHelper, 'action_view/helpers/atom_feed_helper' autoload :CacheHelper, 'action_view/helpers/cache_helper' autoload :CaptureHelper, 'action_view/helpers/capture_helper' + autoload :CsrfHelper, 'action_view/helpers/csrf_helper' autoload :DateHelper, 'action_view/helpers/date_helper' autoload :DebugHelper, 'action_view/helpers/debug_helper' autoload :FormHelper, 'action_view/helpers/form_helper' @@ -40,6 +41,7 @@ module ActionView #:nodoc: include AtomFeedHelper include CacheHelper include CaptureHelper + include CsrfHelper include DateHelper include DebugHelper include FormHelper diff --git a/actionpack/lib/action_view/helpers/csrf_helper.rb b/actionpack/lib/action_view/helpers/csrf_helper.rb new file mode 100644 index 0000000000..2d6af52180 --- /dev/null +++ b/actionpack/lib/action_view/helpers/csrf_helper.rb @@ -0,0 +1,12 @@ +module ActionView + module Helpers + module CsrfHelper + # Returns a meta tag with the request forgery protection token for forms to use. Put this in your head. + def csrf_meta_tag + if protect_against_forgery? + %().html_safe + end + end + end + end +end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index b2a0e2e2a3..55c21bc84a 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -15,13 +15,17 @@ module RequestForgeryProtectionActions render :text => 'pwn' end + def meta + render :inline => "<%= csrf_meta_tag %>" + end + def rescue_action(e) raise e end end # sample controllers class RequestForgeryProtectionController < ActionController::Base include RequestForgeryProtectionActions - protect_from_forgery :only => :index + protect_from_forgery :only => %w(index meta) end class FreeCookieController < RequestForgeryProtectionController @@ -211,6 +215,11 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase ActiveSupport::SecureRandom.stubs(:base64).returns(@token) ActionController::Base.request_forgery_protection_token = :authenticity_token end + + test 'should emit a csrf-token meta tag' do + get :meta + assert_equal %(), @response.body + end end class FreeCookieControllerTest < ActionController::TestCase @@ -238,6 +247,11 @@ class FreeCookieControllerTest < ActionController::TestCase assert_nothing_raised { send(method, :index)} end end + + test 'should not emit a csrf-token meta tag' do + get :meta + assert @response.body.blank? + end end class CustomAuthenticityParamControllerTest < ActionController::TestCase diff --git a/railties/lib/generators/erb/scaffold/templates/layout.html.erb b/railties/lib/generators/erb/scaffold/templates/layout.html.erb index 496de90ebb..420d17f33c 100644 --- a/railties/lib/generators/erb/scaffold/templates/layout.html.erb +++ b/railties/lib/generators/erb/scaffold/templates/layout.html.erb @@ -4,6 +4,7 @@ <%= controller_class_name %>: <%%= controller.action_name %> <%%= stylesheet_link_tag 'scaffold' %> <%%= javascript_include_tag :defaults %> + <%%= csrf_meta_tag %> -- cgit v1.2.3 From 09a88a347d1f94869b945dfaa47ca54dd1940d46 Mon Sep 17 00:00:00 2001 From: Chad Woolley Date: Thu, 4 Feb 2010 15:57:13 -0700 Subject: fix rubygems/bundler install in ci build script Signed-off-by: Jeremy Kemper --- ci/ci_build.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ci/ci_build.rb b/ci/ci_build.rb index b70d59fad4..bf47484320 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -20,10 +20,14 @@ build_results = {} # Install rubygems-update, so 'gem update --system' in cruise_config.rb auto-installs it on next build. # This is how you can auto-update rubygems without logging in to CI system -build_results[:geminstaller] = system "sudo gem install rubygems-update -v 1.3.5 --no-ri --no-rdoc" +rubygems_install_cmd = "sudo gem install rubygems-update -v 1.3.5 --no-ri --no-rdoc" +puts "Running command: #{rubygems_install_cmd}" +build_results[:install_rubygems_update] = system rubygems_install_cmd # Install required version of bundler. -build_results[:geminstaller] = system "sudo gem install bundler -v 0.9.2 --prerelease --no-ri --no-rdoc" +bundler_install_cmd = "sudo gem install bundler -v 0.9.2 --no-ri --no-rdoc" +puts "Running command: #{bundler_install_cmd}" +build_results[:install_bundler] = system bundler_install_cmd cd root_dir do puts -- cgit v1.2.3 From 2191aa47acc0a560366c8c09fa9635602cff5f07 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 15:26:24 -0800 Subject: Expose CSRF param name also --- actionpack/lib/action_view/helpers/csrf_helper.rb | 2 +- actionpack/test/controller/request_forgery_protection_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/helpers/csrf_helper.rb b/actionpack/lib/action_view/helpers/csrf_helper.rb index 2d6af52180..6f98bd4573 100644 --- a/actionpack/lib/action_view/helpers/csrf_helper.rb +++ b/actionpack/lib/action_view/helpers/csrf_helper.rb @@ -4,7 +4,7 @@ module ActionView # Returns a meta tag with the request forgery protection token for forms to use. Put this in your head. def csrf_meta_tag if protect_against_forgery? - %().html_safe + %(\n).html_safe end end end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 55c21bc84a..77d07d8eeb 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -218,7 +218,7 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase test 'should emit a csrf-token meta tag' do get :meta - assert_equal %(), @response.body + assert_equal %(\n), @response.body end end -- cgit v1.2.3 From 3062bc70eff68397a00fc652e8eee4ae8089e0a2 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 17:45:43 -0800 Subject: HTML-escape csrf meta contents --- actionpack/lib/action_view/helpers/csrf_helper.rb | 2 +- actionpack/test/controller/request_forgery_protection_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_view/helpers/csrf_helper.rb b/actionpack/lib/action_view/helpers/csrf_helper.rb index 6f98bd4573..41c6b67f91 100644 --- a/actionpack/lib/action_view/helpers/csrf_helper.rb +++ b/actionpack/lib/action_view/helpers/csrf_helper.rb @@ -4,7 +4,7 @@ module ActionView # Returns a meta tag with the request forgery protection token for forms to use. Put this in your head. def csrf_meta_tag if protect_against_forgery? - %(\n).html_safe + %(\n).html_safe end end end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 77d07d8eeb..c38ffad748 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -210,7 +210,7 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase @request = ActionController::TestRequest.new @request.format = :html @response = ActionController::TestResponse.new - @token = "cf50faa3fe97702ca1ae" + @token = "cf50faa3fe97702ca1a/=?" ActiveSupport::SecureRandom.stubs(:base64).returns(@token) ActionController::Base.request_forgery_protection_token = :authenticity_token @@ -227,7 +227,7 @@ class FreeCookieControllerTest < ActionController::TestCase @controller = FreeCookieController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new - @token = "cf50faa3fe97702ca1ae" + @token = "cf50faa3fe97702ca1a/=?" ActiveSupport::SecureRandom.stubs(:base64).returns(@token) end -- cgit v1.2.3 From 358968cd28b23c79a9311b5f88dce14fed686e97 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 17:46:29 -0800 Subject: Update prototype-ujs for data-confirm --- .../rails/app/templates/public/javascripts/rails.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js index 2a0a05d25f..8e2e0d259d 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js @@ -34,6 +34,12 @@ document.observe("dom:loaded", function() { } $(document.body).observe("click", function(event) { + var message = event.element().readAttribute('data-confirm'); + if (message && !confirm(message)) { + event.stop(); + return false; + } + var element = event.findElement("a[data-remote=true]"); if (element) { handleRemote(element); @@ -41,13 +47,14 @@ document.observe("dom:loaded", function() { } }); - $(document.body).observe("ajax:before", function(event) { - var message = event.element().readAttribute('data-confirm'); - if (message && !confirm(message)) event.stop(); - }); - // TODO: I don't think submit bubbles in IE $(document.body).observe("submit", function(event) { + var message = event.element().readAttribute('data-confirm'); + if (message && !confirm(message)) { + event.stop(); + return false; + } + var inputs = event.element().select("input[type=submit][data-disable-with]"); inputs.each(function(input) { input.disabled = true; -- cgit v1.2.3 From 6bf79f02bede6a75a5211de64a1359b10749a2df Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 17:49:23 -0800 Subject: Revert dumb test --- actionpack/test/controller/request_forgery_protection_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index c38ffad748..77d07d8eeb 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -210,7 +210,7 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase @request = ActionController::TestRequest.new @request.format = :html @response = ActionController::TestResponse.new - @token = "cf50faa3fe97702ca1a/=?" + @token = "cf50faa3fe97702ca1ae" ActiveSupport::SecureRandom.stubs(:base64).returns(@token) ActionController::Base.request_forgery_protection_token = :authenticity_token @@ -227,7 +227,7 @@ class FreeCookieControllerTest < ActionController::TestCase @controller = FreeCookieController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new - @token = "cf50faa3fe97702ca1a/=?" + @token = "cf50faa3fe97702ca1ae" ActiveSupport::SecureRandom.stubs(:base64).returns(@token) end -- cgit v1.2.3 From 7b1d3a0ca38c480ef65e78d28f2b18573b8abd74 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 18:01:08 -0800 Subject: Add prototype ujs handler for data-method --- .../app/templates/public/javascripts/rails.js | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js index 8e2e0d259d..f7ddba390a 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js @@ -1,4 +1,11 @@ document.observe("dom:loaded", function() { + var authToken = $$('meta[name=csrf-token]').first().readAttribute('content'), + authParam = $$('meta[name=csrf-param]').first().readAttribute('content'), + formTemplate = '
\ + #{realmethod}\ +
', + realmethodTemplate = ''; + function handleRemote(element) { var method, url, params; @@ -45,6 +52,25 @@ document.observe("dom:loaded", function() { handleRemote(element); event.stop(); } + + var element = event.findElement("a[data-method]"); + if (element && element.readAttribute('data-remote') != 'true') { + var method = element.readAttribute('data-method'), + piggyback = method.toLowerCase() != 'post', + formHTML = formTemplate.interpolate({ + method: 'POST', + realmethod: piggyback ? realmethodTemplate.interpolate({ method: method }) : '', + action: element.readAttribute('href'), + token: authToken, + param: authParam + }); + + var form = new Element('div').update(formHTML).down().hide(); + this.insert({ bottom: form }); + + form.submit(); + event.stop(); + } }); // TODO: I don't think submit bubbles in IE -- cgit v1.2.3 From 31f8a59c16d4a29553e2dbf891c891493fd138c0 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 18:03:06 -0800 Subject: Test that csrf meta content is html-escaped, too --- actionpack/test/controller/request_forgery_protection_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 77d07d8eeb..be05ef6167 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -217,8 +217,9 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase end test 'should emit a csrf-token meta tag' do + ActiveSupport::SecureRandom.stubs(:base64).returns(@token + '<=?') get :meta - assert_equal %(\n), @response.body + assert_equal %(\n), @response.body end end -- cgit v1.2.3 From c1785f32825431d30a5d826066d37dfb0403cd46 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 18:28:45 -0800 Subject: Release using gemcutter gem:push tasks --- Gemfile | 5 ++++- Rakefile | 14 ++++++++++++++ actionmailer/Rakefile | 23 +++++------------------ actionpack/Rakefile | 6 ++++++ activemodel/Rakefile | 6 ++++++ activerecord/Rakefile | 23 +++++------------------ activeresource/Rakefile | 22 +++++----------------- activesupport/Rakefile | 23 +++++------------------ railties/Rakefile | 23 +++++------------------ 9 files changed, 55 insertions(+), 90 deletions(-) diff --git a/Gemfile b/Gemfile index 3310dd5926..867d35ea2d 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,5 @@ path File.expand_path('..', __FILE__) -source :gemcutter +source 'http://gemcutter.org' gem "rails", "3.0.0.beta" @@ -34,3 +34,6 @@ if ENV['CI'] gem "test-unit", ">= 2.0.5", :require => 'test/unit' end end + +# For releases +gem "rake-gemcutter" diff --git a/Rakefile b/Rakefile index 193e719079..708646e952 100644 --- a/Rakefile +++ b/Rakefile @@ -37,6 +37,20 @@ Rake::GemPackageTask.new(spec) do |pkg| pkg.gem_spec = spec end +Rake::Gemcutter::Tasks(spec) + +desc "Release all gems to gemcutter. Package rails, package & push components, then push rails" +task :release => [:package, :release_all, 'gem:push'] + +desc "Release all components to gemcutter." +task :release_all do + errors = [] + PROJECTS.each do |project| + system(%(cd #{project} && #{env} #{$0} release)) || errors << project + end + fail("Errors in #{errors.join(', ')}") unless errors.empty? +end + task :install => :gem do (PROJECTS - ["railties"]).each do |project| puts "INSTALLING #{project}" diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index 2619d9359e..a1caae97c7 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -4,6 +4,7 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' +require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'action_mailer', 'version') PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' @@ -54,27 +55,13 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -desc "Publish the API documentation" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end +Rake::Gemcutter::Tasks(spec) + +desc "Release to gemcutter" +task :release => [:package, 'gem:push'] desc "Publish the API documentation" task :pdoc => [:rdoc] do require 'rake/contrib/sshpublisher' Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/am", "doc").upload end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rubyforge' - require 'rake/contrib/rubyforgepublisher' - - packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 863daa4b44..e675e67dc6 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -4,6 +4,7 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' +require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'action_pack', 'version') PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' @@ -70,6 +71,11 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end +Rake::Gemcutter::Tasks(spec) + +desc "Release to gemcutter" +task :release => [:package, 'gem:push'] + task :lines do lines, codelines, total_lines, total_codelines = 0, 0, 0, 0 diff --git a/activemodel/Rakefile b/activemodel/Rakefile index f098ce0671..e043a6d69d 100755 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -44,9 +44,15 @@ end require 'rake/packagetask' require 'rake/gempackagetask' +require 'rake/gemcutter' spec = eval(File.read("#{dir}/activemodel.gemspec")) Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end + +Rake::Gemcutter::Tasks(spec) + +desc "Release to gemcutter" +task :release => [:package, 'gem:push'] diff --git a/activerecord/Rakefile b/activerecord/Rakefile index 2511f13fed..ce74beb604 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -4,6 +4,7 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' +require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'active_record', 'version') require File.expand_path(File.dirname(__FILE__)) + "/test/config" @@ -226,27 +227,13 @@ end # Publishing ------------------------------------------------------ -desc "Publish the beta gem" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end +Rake::Gemcutter::Tasks(spec) + +desc "Release to gemcutter" +task :release => [:package, 'gem:push'] desc "Publish the API documentation" task :pdoc => [:rdoc] do require 'rake/contrib/sshpublisher' Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ar", "doc").upload end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rubyforge' - require 'rake/contrib/rubyforgepublisher' - - packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end diff --git a/activeresource/Rakefile b/activeresource/Rakefile index 9fa1f86914..d1bac76517 100644 --- a/activeresource/Rakefile +++ b/activeresource/Rakefile @@ -4,6 +4,7 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' +require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'active_resource', 'version') @@ -89,26 +90,13 @@ end # Publishing ------------------------------------------------------ -desc "Publish the beta gem" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end +Rake::Gemcutter::Tasks(spec) + +desc "Release to gemcutter" +task :release => [:package, 'gem:push'] desc "Publish the API documentation" task :pdoc => [:rdoc] do require 'rake/contrib/sshpublisher' Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ar", "doc").upload end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - `rubyforge login` - - for ext in %w( gem tgz zip ) - release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" - puts release_command - system(release_command) - end -end diff --git a/activesupport/Rakefile b/activesupport/Rakefile index 03ab3b2760..059d99d8ff 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -1,6 +1,7 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/gempackagetask' +require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'active_support', 'version') @@ -49,27 +50,13 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -desc "Publish the beta gem" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end +Rake::Gemcutter::Tasks(spec) + +desc "Release to gemcutter" +task :release => [:package, 'gem:push'] desc "Publish the API documentation" task :pdoc => [:rdoc] do require 'rake/contrib/sshpublisher' Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/as", "doc").upload end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rubyforge' - require 'rake/contrib/rubyforgepublisher' - - packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end diff --git a/railties/Rakefile b/railties/Rakefile index ea0b8ef8fb..808e39f887 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -4,6 +4,7 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask' require 'rake/gempackagetask' +require 'rake/gemcutter' require 'date' require 'rbconfig' @@ -90,12 +91,10 @@ end # Publishing ------------------------------------------------------- -desc "Publish the rails gem" -task :pgem => [:gem] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end +Rake::Gemcutter::Tasks(spec) + +desc "Release to gemcutter" +task :release => [:package, 'gem:push'] desc "Publish the guides" task :pguides => :generate_guides do @@ -105,15 +104,3 @@ task :pguides => :generate_guides do Rake::SshFilePublisher.new("web.rubyonrails.org", "/u/sites/guides.rubyonrails.org/public", "pkg", "guides.gz").upload `ssh web.rubyonrails.org 'cd /u/sites/guides.rubyonrails.org/public/ && tar -xvzf guides.gz && mv guides/output/* . && rm -rf guides*'` end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rake/contrib/rubyforgepublisher' - require 'rubyforge' - - packages = %w( gem ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end -- cgit v1.2.3 From 657ffed3f502856e782a83c95fb6e91b79545c06 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 4 Feb 2010 18:39:19 -0800 Subject: Need gemcutter here too --- Rakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Rakefile b/Rakefile index 708646e952..5f442d1b08 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,7 @@ require 'rake' require 'rake/rdoctask' require 'rake/gempackagetask' +require 'rake/gemcutter' env = %(PKG_BUILD="#{ENV['PKG_BUILD']}") if ENV['PKG_BUILD'] -- cgit v1.2.3 From ed6e72a84f43ef485e5f41f0f56988cc7c79f502 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 18:39:41 -0800 Subject: No sense bundling sense it's not available in Rakefile. Also, actually require. --- Gemfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Gemfile b/Gemfile index 867d35ea2d..bec83b5dad 100644 --- a/Gemfile +++ b/Gemfile @@ -34,6 +34,3 @@ if ENV['CI'] gem "test-unit", ">= 2.0.5", :require => 'test/unit' end end - -# For releases -gem "rake-gemcutter" -- cgit v1.2.3 From 7b81f5981fd6dfcede61a89da80b09a1650e2c02 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 18:44:14 -0800 Subject: Fix task defines --- Rakefile | 2 +- actionmailer/Rakefile | 2 +- actionpack/Rakefile | 2 +- activemodel/Rakefile | 2 +- activerecord/Rakefile | 2 +- activeresource/Rakefile | 2 +- activesupport/Rakefile | 2 +- railties/Rakefile | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Rakefile b/Rakefile index 5f442d1b08..99be4e0711 100644 --- a/Rakefile +++ b/Rakefile @@ -38,7 +38,7 @@ Rake::GemPackageTask.new(spec) do |pkg| pkg.gem_spec = spec end -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release all gems to gemcutter. Package rails, package & push components, then push rails" task :release => [:package, :release_all, 'gem:push'] diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index a1caae97c7..d63e092e10 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -55,7 +55,7 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release to gemcutter" task :release => [:package, 'gem:push'] diff --git a/actionpack/Rakefile b/actionpack/Rakefile index e675e67dc6..5122b44f4e 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -71,7 +71,7 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release to gemcutter" task :release => [:package, 'gem:push'] diff --git a/activemodel/Rakefile b/activemodel/Rakefile index e043a6d69d..565277d6bd 100755 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -52,7 +52,7 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release to gemcutter" task :release => [:package, 'gem:push'] diff --git a/activerecord/Rakefile b/activerecord/Rakefile index ce74beb604..aee8e49ada 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -227,7 +227,7 @@ end # Publishing ------------------------------------------------------ -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release to gemcutter" task :release => [:package, 'gem:push'] diff --git a/activeresource/Rakefile b/activeresource/Rakefile index d1bac76517..61804df40e 100644 --- a/activeresource/Rakefile +++ b/activeresource/Rakefile @@ -90,7 +90,7 @@ end # Publishing ------------------------------------------------------ -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release to gemcutter" task :release => [:package, 'gem:push'] diff --git a/activesupport/Rakefile b/activesupport/Rakefile index 059d99d8ff..160802b10d 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -50,7 +50,7 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release to gemcutter" task :release => [:package, 'gem:push'] diff --git a/railties/Rakefile b/railties/Rakefile index 808e39f887..fad60e50c9 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -91,7 +91,7 @@ end # Publishing ------------------------------------------------------- -Rake::Gemcutter::Tasks(spec) +Rake::Gemcutter::Tasks.new(spec).define desc "Release to gemcutter" task :release => [:package, 'gem:push'] -- cgit v1.2.3 From b1f30ef048aeee5f79399581fe9da847d5be78c2 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 19:13:07 -0800 Subject: Kill default require_path --- rails.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rails.gemspec b/rails.gemspec index a904d3d08b..4b3c174888 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -10,8 +10,8 @@ Gem::Specification.new do |s| s.homepage = 'http://www.rubyonrails.org' s.rubyforge_project = 'rails' - s.rdoc_options << '--exclude' << '.' - s.has_rdoc = false + s.files = [] + s.require_path = [] s.add_dependency('activesupport', '= 3.0.0.beta') s.add_dependency('actionpack', '= 3.0.0.beta') -- cgit v1.2.3 From ae4cb0641ed5505c99f3ba6eef35a83c263bfe98 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 23:53:10 -0800 Subject: Add the dummy rails3b gemspec that pulls in non-prerelease deps --- rails3b.gemspec | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 rails3b.gemspec diff --git a/rails3b.gemspec b/rails3b.gemspec new file mode 100644 index 0000000000..4aa342e6c0 --- /dev/null +++ b/rails3b.gemspec @@ -0,0 +1,27 @@ +Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = 'rails3b' + s.version = '3.0.0' + s.summary = 'Just the Rails 3 beta dependencies. Works around prerelease RubyGems bug.' + s.description = 'My kingdom for working dependencies.' + + s.author = 'Jeremy Kemper' + s.email = 'jeremy@bitsweat.net' + + s.files = [] + s.require_path = [] + + s.add_dependency('mail', '~> 2.1.2') + s.add_dependency('text-format', '~> 1.0.0') + s.add_dependency('rack', '~> 1.1.0') + s.add_dependency('rack-test', '~> 0.5.0') + s.add_dependency('rack-mount', '~> 0.4.0') + s.add_dependency('erubis', '~> 2.6.5') + s.add_dependency('i18n', '~> 0.3.0') + s.add_dependency('tzinfo', '~> 0.3.16') + s.add_dependency('builder', '~> 2.1.2') + s.add_dependency('memcache-client', '~> 1.7.5') + s.add_dependency('bundler', '>= 0.9.2') + s.add_dependency('rake', '>= 0.8.3') + s.add_dependency('thor', '~> 0.13') +end -- cgit v1.2.3 From 459ecaf95db12ec64e70c02f8ee58ddb1133021e Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 00:03:03 -0800 Subject: Submarine the rake-gemcutter dep in Rakefiles --- Rakefile | 13 +++++++------ actionmailer/Rakefile | 9 +++++---- actionpack/Rakefile | 9 +++++---- activemodel/Rakefile | 9 +++++---- activerecord/Rakefile | 9 +++++---- activeresource/Rakefile | 9 +++++---- activesupport/Rakefile | 9 +++++---- railties/Rakefile | 9 +++++---- 8 files changed, 42 insertions(+), 34 deletions(-) diff --git a/Rakefile b/Rakefile index 99be4e0711..96d69bd33e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,6 @@ require 'rake' require 'rake/rdoctask' require 'rake/gempackagetask' -require 'rake/gemcutter' env = %(PKG_BUILD="#{ENV['PKG_BUILD']}") if ENV['PKG_BUILD'] @@ -14,7 +13,7 @@ end desc 'Run all tests by default' task :default => %w(test test:isolated) -%w(test test:isolated rdoc pgem package release gem gemspec).each do |task_name| +%w(test test:isolated rdoc pgem package gem gemspec).each do |task_name| desc "Run #{task_name} task for all projects" task task_name do errors = [] @@ -38,13 +37,15 @@ Rake::GemPackageTask.new(spec) do |pkg| pkg.gem_spec = spec end -Rake::Gemcutter::Tasks.new(spec).define - desc "Release all gems to gemcutter. Package rails, package & push components, then push rails" -task :release => [:package, :release_all, 'gem:push'] +task :release => :release_projects do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end desc "Release all components to gemcutter." -task :release_all do +task :release_projects => :package do errors = [] PROJECTS.each do |project| system(%(cd #{project} && #{env} #{$0} release)) || errors << project diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index d63e092e10..baea591b97 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -4,7 +4,6 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' -require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'action_mailer', 'version') PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' @@ -55,10 +54,12 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks.new(spec).define - desc "Release to gemcutter" -task :release => [:package, 'gem:push'] +task :release => :package do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end desc "Publish the API documentation" task :pdoc => [:rdoc] do diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 5122b44f4e..c45f88ed04 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -4,7 +4,6 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' -require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'action_pack', 'version') PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' @@ -71,10 +70,12 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks.new(spec).define - desc "Release to gemcutter" -task :release => [:package, 'gem:push'] +task :release => :package do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end task :lines do lines, codelines, total_lines, total_codelines = 0, 0, 0, 0 diff --git a/activemodel/Rakefile b/activemodel/Rakefile index 565277d6bd..5ea7b373fc 100755 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -44,7 +44,6 @@ end require 'rake/packagetask' require 'rake/gempackagetask' -require 'rake/gemcutter' spec = eval(File.read("#{dir}/activemodel.gemspec")) @@ -52,7 +51,9 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks.new(spec).define - desc "Release to gemcutter" -task :release => [:package, 'gem:push'] +task :release => :package do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end diff --git a/activerecord/Rakefile b/activerecord/Rakefile index aee8e49ada..8a414a751b 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -4,7 +4,6 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' -require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'active_record', 'version') require File.expand_path(File.dirname(__FILE__)) + "/test/config" @@ -227,10 +226,12 @@ end # Publishing ------------------------------------------------------ -Rake::Gemcutter::Tasks.new(spec).define - desc "Release to gemcutter" -task :release => [:package, 'gem:push'] +task :release => :package do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end desc "Publish the API documentation" task :pdoc => [:rdoc] do diff --git a/activeresource/Rakefile b/activeresource/Rakefile index 61804df40e..829752516f 100644 --- a/activeresource/Rakefile +++ b/activeresource/Rakefile @@ -4,7 +4,6 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/packagetask' require 'rake/gempackagetask' -require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'active_resource', 'version') @@ -90,10 +89,12 @@ end # Publishing ------------------------------------------------------ -Rake::Gemcutter::Tasks.new(spec).define - desc "Release to gemcutter" -task :release => [:package, 'gem:push'] +task :release => :package do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end desc "Publish the API documentation" task :pdoc => [:rdoc] do diff --git a/activesupport/Rakefile b/activesupport/Rakefile index 160802b10d..357bdca715 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -1,7 +1,6 @@ require 'rake/testtask' require 'rake/rdoctask' require 'rake/gempackagetask' -require 'rake/gemcutter' require File.join(File.dirname(__FILE__), 'lib', 'active_support', 'version') @@ -50,10 +49,12 @@ Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec end -Rake::Gemcutter::Tasks.new(spec).define - desc "Release to gemcutter" -task :release => [:package, 'gem:push'] +task :release => :package do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end desc "Publish the API documentation" task :pdoc => [:rdoc] do diff --git a/railties/Rakefile b/railties/Rakefile index fad60e50c9..f32a794544 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -4,7 +4,6 @@ require 'rake' require 'rake/testtask' require 'rake/rdoctask' require 'rake/gempackagetask' -require 'rake/gemcutter' require 'date' require 'rbconfig' @@ -91,10 +90,12 @@ end # Publishing ------------------------------------------------------- -Rake::Gemcutter::Tasks.new(spec).define - desc "Release to gemcutter" -task :release => [:package, 'gem:push'] +task :release => :package do + require 'rake/gemcutter' + Rake::Gemcutter::Tasks.new(spec).define + Rake::Task['gem:push'].invoke +end desc "Publish the guides" task :pguides => :generate_guides do -- cgit v1.2.3 From 363a752c36122c92d528aee83262f3ee2db460ae Mon Sep 17 00:00:00 2001 From: Paul Rosania Date: Fri, 5 Feb 2010 00:11:09 -0500 Subject: install ActionController::UrlFor before environment is parsed, to provide ActionMailer#default_url_options= Signed-off-by: Jeremy Kemper --- actionmailer/lib/action_mailer/railtie.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index b5230f14ed..a3afc23e6a 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -5,6 +5,10 @@ module ActionMailer class Railtie < Rails::Railtie railtie_name :action_mailer + initializer "action_mailer.url_for", :before => :load_environment_config do |app| + ActionMailer::Base.send(:include, ActionController::UrlFor) if defined?(ActionController) + end + require "action_mailer/railties/subscriber" subscriber ActionMailer::Railties::Subscriber.new @@ -17,9 +21,5 @@ module ActionMailer ActionMailer::Base.send "#{k}=", v end end - - initializer "action_mailer.url_for" do |app| - ActionMailer::Base.send(:include, ActionController::UrlFor) if defined?(ActionController) - end end -end +end \ No newline at end of file -- cgit v1.2.3 From f1e5642fb7e99ed5c26e863596bc2ea1e7176fba Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 09:12:35 -0800 Subject: Revert "Link to main Arel repository" This reverts commit 203626867934a2772a5a3f096521b56d59273407. --- railties/guides/source/3_0_release_notes.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/3_0_release_notes.textile b/railties/guides/source/3_0_release_notes.textile index 7679302ff9..5e96f8cf06 100644 --- a/railties/guides/source/3_0_release_notes.textile +++ b/railties/guides/source/3_0_release_notes.textile @@ -8,7 +8,7 @@ Even if you don't give a hoot about any of our internal cleanups, Rails 3.0 is g * Brand new router with an emphasis on RESTful declarations * New Action Mailer API modelled after Action Controller (now without the agonizing pain of sending multipart messages!) -* New Active Record chainable query language built on top of "Arel":http://github.com/brynary/arel, a relational algebra engine +* New Active Record chainable query language built on top of relational algebra * Unobtrusive JavaScript helpers with drivers for Prototype, jQuery, and more coming (end of inline JS) * Explicit dependency management with Bundler @@ -131,7 +131,7 @@ More Information: - "Rails Edge Architecture":http://yehudakatz.com/2009/06/11/r h4. Arel Integration -"Arel":http://github.com/brynary/arel (or Active Relation) has been taken on as the underpinnings of Active Record and is now required for Rails. Arel provides an SQL abstraction that simplifies out Active Record and provides the underpinnings for the relation functionality in Active Record. +"Arel":http://github.com/rails/arel (or Active Relation) has been taken on as the underpinnings of Active Record and is now required for Rails. Arel provides an SQL abstraction that simplifies out Active Record and provides the underpinnings for the relation functionality in Active Record. More information: - "Why I wrote Arel":http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/. -- cgit v1.2.3 From a81a2a29ab7d14a265364a9cd8889261c896b827 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 09:21:45 -0800 Subject: Bump arel dep --- activerecord/activerecord.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index f7ed77ca4b..8d9708ef1b 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -19,5 +19,5 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', '= 3.0.0.beta') s.add_dependency('activemodel', '= 3.0.0.beta') - s.add_dependency('arel', '~> 0.2.0') + s.add_dependency('arel', '~> 0.2.1') end -- cgit v1.2.3 From c548e213658386f3a5b00097bc5b30bf3736e6b4 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 09:24:12 -0800 Subject: Bump git versions to 3.0.0.beta1 since we've released --- Gemfile | 2 +- actionmailer/actionmailer.gemspec | 4 ++-- actionpack/actionpack.gemspec | 6 +++--- activemodel/activemodel.gemspec | 4 ++-- activerecord/activerecord.gemspec | 6 +++--- activeresource/activeresource.gemspec | 6 +++--- activesupport/activesupport.gemspec | 2 +- rails.gemspec | 14 +++++++------- railties/lib/rails/tasks/documentation.rake | 2 +- railties/railties.gemspec | 6 +++--- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Gemfile b/Gemfile index bec83b5dad..0775e8eb98 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ path File.expand_path('..', __FILE__) source 'http://gemcutter.org' -gem "rails", "3.0.0.beta" +gem "rails", "3.0.0.beta1" gem "rake", ">= 0.8.7" gem "mocha", ">= 0.9.8" diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index c3b1c96832..d5c0a4c9c4 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'actionmailer' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = 'Email composition, delivery, and recieval framework (part of Rails).' s.description = 'Email composition, delivery, and recieval framework (part of Rails).' @@ -16,7 +16,7 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency('actionpack', '= 3.0.0.beta') + s.add_dependency('actionpack', '= 3.0.0.beta1') s.add_dependency('mail', '~> 2.1.2') s.add_dependency('text-format', '~> 1.0.0') end diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 2017776661..ef141f2202 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'actionpack' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = 'Web-flow and rendering framework putting the VC in MVC (part of Rails).' s.description = 'Web-flow and rendering framework putting the VC in MVC (part of Rails).' @@ -16,8 +16,8 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency('activesupport', '= 3.0.0.beta') - s.add_dependency('activemodel', '= 3.0.0.beta') + s.add_dependency('activesupport', '= 3.0.0.beta1') + s.add_dependency('activemodel', '= 3.0.0.beta1') s.add_dependency('rack', '~> 1.1.0') s.add_dependency('rack-test', '~> 0.5.0') s.add_dependency('rack-mount', '~> 0.4.0') diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index 64ae6e0760..e5b0207e39 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'activemodel' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = "A toolkit for building other modeling frameworks like ActiveRecord" s.description = %q{Extracts common modeling concerns from ActiveRecord to share between similar frameworks like ActiveResource.} @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency('activesupport', '= 3.0.0.beta') + s.add_dependency('activesupport', '= 3.0.0.beta1') s.require_path = 'lib' s.files = Dir["CHANGELOG", "MIT-LICENSE", "README", "lib/**/*"] diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index 8d9708ef1b..82a31b262b 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'activerecord' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = 'Object-relational mapper framework (part of Rails).' s.description = 'Object-relational mapper framework (part of Rails).' @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.extra_rdoc_files = %w( README ) s.rdoc_options.concat ['--main', 'README'] - s.add_dependency('activesupport', '= 3.0.0.beta') - s.add_dependency('activemodel', '= 3.0.0.beta') + s.add_dependency('activesupport', '= 3.0.0.beta1') + s.add_dependency('activemodel', '= 3.0.0.beta1') s.add_dependency('arel', '~> 0.2.1') end diff --git a/activeresource/activeresource.gemspec b/activeresource/activeresource.gemspec index 8668761977..51a381ccc8 100644 --- a/activeresource/activeresource.gemspec +++ b/activeresource/activeresource.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'activeresource' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = 'REST-model framework (part of Rails).' s.description = 'REST-model framework (part of Rails).' @@ -17,6 +17,6 @@ Gem::Specification.new do |s| s.extra_rdoc_files = %w( README ) s.rdoc_options.concat ['--main', 'README'] - s.add_dependency('activesupport', '= 3.0.0.beta') - s.add_dependency('activemodel', '= 3.0.0.beta') + s.add_dependency('activesupport', '= 3.0.0.beta1') + s.add_dependency('activemodel', '= 3.0.0.beta1') end diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index c366ccfa8e..d169392dfc 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'activesupport' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = 'Support and utility classes used by the Rails framework.' s.description = 'Support and utility classes used by the Rails framework.' diff --git a/rails.gemspec b/rails.gemspec index 4b3c174888..3c293a250f 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'rails' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = 'Full-stack web-application framework.' s.description = 'Full-stack web-application framework.' @@ -13,11 +13,11 @@ Gem::Specification.new do |s| s.files = [] s.require_path = [] - s.add_dependency('activesupport', '= 3.0.0.beta') - s.add_dependency('actionpack', '= 3.0.0.beta') - s.add_dependency('activerecord', '= 3.0.0.beta') - s.add_dependency('activeresource', '= 3.0.0.beta') - s.add_dependency('actionmailer', '= 3.0.0.beta') - s.add_dependency('railties', '= 3.0.0.beta') + s.add_dependency('activesupport', '= 3.0.0.beta1') + s.add_dependency('actionpack', '= 3.0.0.beta1') + s.add_dependency('activerecord', '= 3.0.0.beta1') + s.add_dependency('activeresource', '= 3.0.0.beta1') + s.add_dependency('actionmailer', '= 3.0.0.beta1') + s.add_dependency('railties', '= 3.0.0.beta1') s.add_dependency('bundler', '>= 0.9.2') end diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake index 7095046f21..f7cc6ff4be 100644 --- a/railties/lib/rails/tasks/documentation.rake +++ b/railties/lib/rails/tasks/documentation.rake @@ -14,7 +14,7 @@ namespace :doc do desc 'Generate documentation for the Rails framework. Specify path with PATH="/path/to/rails"' Rake::RDocTask.new("rails") { |rdoc| path = ENV['RAILS_PATH'] || 'vendor/gems/gems' - version = '-3.0.0.beta' unless ENV['RAILS_PATH'] + version = '-3.0.0.beta1' unless ENV['RAILS_PATH'] rdoc.rdoc_dir = 'doc/api' rdoc.template = "#{ENV['template']}.rb" if ENV['template'] rdoc.title = "Rails Framework Documentation" diff --git a/railties/railties.gemspec b/railties/railties.gemspec index e91bd0e1b5..4fedb64c93 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'railties' - s.version = '3.0.0.beta' + s.version = '3.0.0.beta1' s.summary = 'Controls boot-up, rake tasks and generators for the Rails framework.' s.description = 'Controls boot-up, rake tasks and generators for the Rails framework.' @@ -21,6 +21,6 @@ Gem::Specification.new do |s| s.add_dependency('rake', '>= 0.8.3') s.add_dependency('thor', '~> 0.13') - s.add_dependency('activesupport', '= 3.0.0.beta') - s.add_dependency('actionpack', '= 3.0.0.beta') + s.add_dependency('activesupport', '= 3.0.0.beta1') + s.add_dependency('actionpack', '= 3.0.0.beta1') end -- cgit v1.2.3 From a96bf4ab5e73fccdafb78b99e8a122cc2172b505 Mon Sep 17 00:00:00 2001 From: Brian Lopez Date: Tue, 26 Jan 2010 08:40:35 -0800 Subject: Add yajl-ruby as a JSON parsing backend [#2666 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/CHANGELOG | 5 +++ .../lib/active_support/json/backends/yajl.rb | 40 ++++++++++++++++++++++ activesupport/test/json/decoding_test.rb | 1 + 3 files changed, 46 insertions(+) create mode 100644 activesupport/lib/active_support/json/backends/yajl.rb diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 431607f4e0..71eeff3a53 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,10 @@ *Rails 3.0 (pending)* +* JSON backend for YAJL. #2666 [Brian Lopez] + + +*Rails 3.0.0 [beta] (February 4, 2010)* + * Introduce class_attribute to declare inheritable class attributes. Writing an attribute on a subclass behaves just like overriding the superclass reader method. Unifies and replaces most usage of cattr_accessor, class_inheritable_attribute, superclass_delegating_attribute, and extlib_inheritable_attribute. [Jeremy Kemper, Yehuda Katz] * Time#- with a DateTime argument behaves the same as with a Time argument, i.e. returns the difference between self and arg as a Float #3476 [Geoff Buesing] diff --git a/activesupport/lib/active_support/json/backends/yajl.rb b/activesupport/lib/active_support/json/backends/yajl.rb new file mode 100644 index 0000000000..d76f8b03e4 --- /dev/null +++ b/activesupport/lib/active_support/json/backends/yajl.rb @@ -0,0 +1,40 @@ +require 'yajl-ruby' unless defined?(Yajl) + +module ActiveSupport + module JSON + module Backends + module Yajl + ParseError = ::Yajl::ParseError + extend self + + # Parses a JSON string or IO and convert it into an object + def decode(json) + data = ::Yajl::Parser.new.parse(json) + if ActiveSupport.parse_json_times + convert_dates_from(data) + else + data + end + end + + private + def convert_dates_from(data) + case data + when nil + nil + when DATE_REGEX + DateTime.parse(data) + when Array + data.map! { |d| convert_dates_from(d) } + when Hash + data.each do |key, value| + data[key] = convert_dates_from(value) + end + else + data + end + end + end + end + end +end diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 8fcb16abfb..fbd75a8966 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -49,6 +49,7 @@ class TestJSONDecoding < ActiveSupport::TestCase backends = %w(Yaml) backends << "JSONGem" if defined?(::JSON) + backends << "Yajl" if defined?(::Yajl) backends.each do |backend| TESTS.each do |json, expected| -- cgit v1.2.3 From 63bb955a99eb46e257655c93dd64e86ebbf05651 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 10:16:30 -0800 Subject: Automatically prefer Yajl or JSON backend over Yaml, if available --- activesupport/CHANGELOG | 2 +- activesupport/lib/active_support/json/decoding.rb | 17 ++++++++++++++++- activesupport/test/json/decoding_test.rb | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 71eeff3a53..8ec903e376 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,6 +1,6 @@ *Rails 3.0 (pending)* -* JSON backend for YAJL. #2666 [Brian Lopez] +* JSON backend for YAJL. Preferred if available. #2666 [Brian Lopez] *Rails 3.0.0 [beta] (February 4, 2010)* diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index a5908365af..e357b6837a 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -6,12 +6,15 @@ module ActiveSupport mattr_accessor :parse_json_times module JSON + # Listed in order of preference. + DECODERS = %w(Yajl JSONGem Yaml) + class << self attr_reader :parse_error delegate :decode, :to => :backend def backend - self.backend = "Yaml" unless defined?(@backend) + set_default_backend unless defined?(@backend) @backend end @@ -31,6 +34,18 @@ module ActiveSupport ensure self.backend = old_backend end + + def set_default_backend + DECODERS.find do |name| + begin + self.backend = name + true + rescue LoadError + # Try next decoder. + false + end + end + end end end end diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index fbd75a8966..d2e3efaa6b 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -45,7 +45,7 @@ class TestJSONDecoding < ActiveSupport::TestCase } # load the default JSON backend - ActiveSupport::JSON.backend + ActiveSupport::JSON.backend = 'Yaml' backends = %w(Yaml) backends << "JSONGem" if defined?(::JSON) -- cgit v1.2.3 From fd567785f4670b31db300324642cf2464025313e Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 12:23:22 -0800 Subject: Make UrlWriter includable in a Module --- actionpack/lib/action_controller/metal/url_for.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 51702368c1..4f3ad07be5 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/module/attribute_accessors' module ActionController # In routes.rb one defines URL-to-controller mappings, but the reverse @@ -87,7 +88,14 @@ module ActionController included do ActionController::Routing::Routes.install_helpers(self) - class_attribute :default_url_options + + # Including in a class uses an inheritable hash. Modules get a plain hash. + if respond_to?(:class_attribute) + class_attribute :default_url_options + else + mattr_accessor :default_url_options + end + self.default_url_options = {} end -- cgit v1.2.3 From 293c53ab3e3795cf0837c0b9225d64b3d906b8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santiago=20Pastorino=20and=20Jos=C3=A9=20Ignacio=20Costa?= Date: Wed, 3 Feb 2010 19:38:58 -0200 Subject: Fixed html_safe test cases which weren't testing correctly [#3845 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/test/core_ext/string_ext_test.rb | 37 ++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index ca26f91e8c..d8145d467b 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -335,6 +335,11 @@ end class OutputSafetyTest < ActiveSupport::TestCase def setup @string = "hello" + @object = Class.new(Object) do + def to_s + "other" + end + end.new end test "A string is unsafe by default" do @@ -355,17 +360,15 @@ class OutputSafetyTest < ActiveSupport::TestCase end test "An object is unsafe by default" do - klass = Class.new(Object) do - def to_str - "other" - end - end + assert !@object.html_safe? + end - @string.html_safe - @string << klass.new + test "Adding an object to a safe string returns a safe string" do + string = @string.html_safe + string << @object - assert_equal "helloother", @string - assert !@string.html_safe? + assert_equal "helloother", string + assert string.html_safe? end test "Adding a safe string to another safe string returns a safe string" do @@ -391,9 +394,9 @@ class OutputSafetyTest < ActiveSupport::TestCase test "Concatting safe onto unsafe yields unsafe" do @other_string = "other" - @string.html_safe - @other_string.concat(@string) + string = @string.html_safe + @other_string.concat(string) assert !@other_string.html_safe? end @@ -406,17 +409,17 @@ class OutputSafetyTest < ActiveSupport::TestCase test "Concatting safe onto safe yields safe" do @other_string = "other".html_safe - @string.html_safe + string = @string.html_safe - @other_string.concat(@string) + @other_string.concat(string) assert @other_string.html_safe? end test "Concatting safe onto unsafe with << yields unsafe" do @other_string = "other" - @string.html_safe + string = @string.html_safe - @other_string << @string + @other_string << string assert !@other_string.html_safe? end @@ -429,9 +432,9 @@ class OutputSafetyTest < ActiveSupport::TestCase test "Concatting safe onto safe with << yields safe" do @other_string = "other".html_safe - @string.html_safe + string = @string.html_safe - @other_string << @string + @other_string << string assert @other_string.html_safe? end -- cgit v1.2.3 From c65f4b1ffb3862909df7c883f3486e08425bdc6a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Feb 2010 09:54:54 -0200 Subject: Making SafeBuffer << an alias for concat method [#3848 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/lib/active_support/core_ext/string/output_safety.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 3977971e8d..567ba00b0d 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -71,15 +71,12 @@ module ActiveSupport #:nodoc: super(ERB::Util.h(value)) end end + alias << concat def +(other) dup.concat(other) end - def <<(value) - self.concat(value) - end - def html_safe? true end @@ -102,4 +99,4 @@ class String def html_safe ActiveSupport::SafeBuffer.new(self) end -end \ No newline at end of file +end -- cgit v1.2.3 From e115eb097e3e5704b9861b6f2b92cc25d23de07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santiago=20Pastorino=20and=20Jos=C3=A9=20Ignacio=20Costa?= Date: Thu, 4 Feb 2010 21:14:46 -0200 Subject: More html_safe strings now use the safe_concat method [#3856 state:committed] Signed-off-by: Jeremy Kemper --- actionpack/lib/action_view/helpers/form_helper.rb | 2 +- actionpack/lib/action_view/helpers/form_tag_helper.rb | 6 +++--- actionpack/lib/action_view/helpers/javascript_helper.rb | 2 +- actionpack/lib/action_view/helpers/tag_helper.rb | 2 +- actionpack/lib/action_view/render/rendering.rb | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index c2ad7e9f77..238f2eb07a 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -309,7 +309,7 @@ module ActionView options[:html][:remote] = true if options.delete(:remote) - concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {})) + safe_concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {})) fields_for(object_name, *(args << options), &proc) safe_concat('') end diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index ba1b0bcc20..6ed6c3101b 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -441,8 +441,8 @@ module ActionView # # =>

def field_set_tag(legend = nil, options = nil, &block) content = capture(&block) - concat(tag(:fieldset, options, true)) - concat(content_tag(:legend, legend)) unless legend.blank? + safe_concat(tag(:fieldset, options, true)) + safe_concat(content_tag(:legend, legend)) unless legend.blank? concat(content) safe_concat("") end @@ -477,7 +477,7 @@ module ActionView def form_tag_in_block(html_options, &block) content = capture(&block) - concat(form_tag_html(html_options)) + safe_concat(form_tag_html(html_options)) concat(content) safe_concat("") end diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 7dca9849c0..8fdaa8cf8d 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -86,7 +86,7 @@ module ActionView tag = content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS)) if block_called_from_erb?(block) - concat(tag) + safe_concat(tag) else tag end diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index ed80e07c78..a3a8185f40 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -72,7 +72,7 @@ module ActionView content_tag = content_tag_string(name, capture(&block), options, escape) if block_called_from_erb?(block) - concat(content_tag) + safe_concat(content_tag) else content_tag end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 7c33f1334a..abc7c09991 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -19,7 +19,7 @@ module ActionView options[:locals] ||= {} if block_given? - return concat(_render_partial(options.merge(:partial => layout), &block)) + return safe_concat(_render_partial(options.merge(:partial => layout), &block)) elsif options.key?(:partial) return _render_partial(options) end -- cgit v1.2.3 From 44c46558a4a710805e0ebadfb008da0d1a39b90b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 1 Feb 2010 01:18:55 -0200 Subject: test_validates_acceptance_of_as_database_column fixed [#3826 state:committed] Signed-off-by: Jeremy Kemper --- activerecord/test/cases/validations_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index 5aac0229cd..937e08ac68 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -157,9 +157,9 @@ class ValidationsTest < ActiveRecord::TestCase end def test_validates_acceptance_of_as_database_column - Topic.validates_acceptance_of(:author_name) - topic = Topic.create("author_name" => "Dan Brown") - assert_equal "Dan Brown", topic["author_name"] + Topic.validates_acceptance_of(:approved) + topic = Topic.create("approved" => true) + assert topic["approved"] end def test_validate_is_deprecated_on_create -- cgit v1.2.3 From a9620ab918b555fc963013e7f5417dbff4e87db3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 31 Jan 2010 18:54:48 -0200 Subject: method_missing errors on activeresource tests, mocha is not required there [#3825 state:committed] Signed-off-by: Jeremy Kemper --- activeresource/test/cases/base_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activeresource/test/cases/base_test.rb b/activeresource/test/cases/base_test.rb index 91349b810a..e73701cad7 100644 --- a/activeresource/test/cases/base_test.rb +++ b/activeresource/test/cases/base_test.rb @@ -5,6 +5,7 @@ require "fixtures/street_address" require "fixtures/beast" require "fixtures/proxy" require 'active_support/core_ext/hash/conversions' +require 'mocha' class BaseTest < Test::Unit::TestCase def setup -- cgit v1.2.3 From 86df107eff7722b3808edbf5a1c4ee2514ed3969 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 16:17:06 -0800 Subject: CI: add missing isolated tests --- ci/ci_build.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ci/ci_build.rb b/ci/ci_build.rb index bf47484320..9889bd7918 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -64,6 +64,7 @@ cd "#{root_dir}/actionmailer" do puts "[CruiseControl] Building ActionMailer" puts build_results[:actionmailer] = rake 'test' + build_results[:actionmailer_isolated] = rake 'test:isolated' end cd "#{root_dir}/activemodel" do @@ -71,6 +72,7 @@ cd "#{root_dir}/activemodel" do puts "[CruiseControl] Building ActiveModel" puts build_results[:activemodel] = rake 'test' + build_results[:activemodel_isolated] = rake 'test:isolated' end rm_f "#{root_dir}/activeresource/debug.log" @@ -79,6 +81,7 @@ cd "#{root_dir}/activeresource" do puts "[CruiseControl] Building ActiveResource" puts build_results[:activeresource] = rake 'test' + build_results[:activeresource_isolated] = rake 'test:isolated' end rm_f "#{root_dir}/activerecord/debug.log" @@ -86,21 +89,24 @@ cd "#{root_dir}/activerecord" do puts puts "[CruiseControl] Building ActiveRecord with MySQL" puts - build_results[:activerecord_mysql] = rake 'mysql:rebuild_databases', 'test_mysql' + build_results[:activerecord_mysql] = rake 'mysql:rebuild_databases', 'mysql:test' + build_results[:activerecord_mysql_isolated] = rake 'mysql:rebuild_databases', 'mysql:isolated_test' end cd "#{root_dir}/activerecord" do puts puts "[CruiseControl] Building ActiveRecord with PostgreSQL" puts - build_results[:activerecord_postgresql8] = rake 'postgresql:rebuild_databases', 'test_postgresql' + build_results[:activerecord_postgresql8] = rake 'postgresql:rebuild_databases', 'postgresql:test' + build_results[:activerecord_postgresql8_isolated] = rake 'postgresql:rebuild_databases', 'postgresql:isolated_test' end cd "#{root_dir}/activerecord" do puts puts "[CruiseControl] Building ActiveRecord with SQLite 3" puts - build_results[:activerecord_sqlite3] = rake 'test_sqlite3' + build_results[:activerecord_sqlite3] = rake 'sqlite3:test' + build_results[:activerecord_sqlite3_isolated] = rake 'sqlite3:isolated_test' end -- cgit v1.2.3 From 47db62bf8dc380d31f1c106a2cb39b18b7cbf36f Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 16:18:26 -0800 Subject: CI: show bundled gems --- ci/ci_build.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ci/ci_build.rb b/ci/ci_build.rb index 9889bd7918..4c3a894b47 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -119,9 +119,8 @@ puts "[CruiseControl] #{`mysql --version`}" puts "[CruiseControl] #{`pg_config --version`}" puts "[CruiseControl] SQLite3: #{`sqlite3 -version`}" `gem env`.each_line {|line| print "[CruiseControl] #{line}"} -# Commented until bundler supports --list again -# puts "[CruiseControl] Bundled gems:" -# `gem bundle --list`.each_line {|line| print "[CruiseControl] #{line}"} +puts "[CruiseControl] Bundled gems:" +`bundle show`.each_line {|line| print "[CruiseControl] #{line}"} puts "[CruiseControl] Local gems:" `gem list`.each_line {|line| print "[CruiseControl] #{line}"} -- cgit v1.2.3 From 6201abe73f7100b93727c6a0d549651df737948a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:33:24 -0800 Subject: New style for path references --- railties/lib/generators/rails/app/templates/Gemfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index f51edc4d2f..1ceb5a7bcc 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -7,8 +7,7 @@ gem "rails", "<%= Rails::VERSION::STRING %>" ## Bundle edge rails: <%- if options.dev? -%> -path "<%= Rails::Generators::RAILS_DEV_PATH %>", :glob => "{*/,}*.gemspec" -gem "rails", "<%= Rails::VERSION::STRING %>" +gem "rails", "<%= Rails::VERSION::STRING %>", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" <%- else -%> <%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> -- cgit v1.2.3 From 0ce9c80c0a3a7d09ffd61f8b09093afbb6239c14 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:35:19 -0800 Subject: Path approach shouldnt specify version --- railties/lib/generators/rails/app/templates/Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 1ceb5a7bcc..54aa53a181 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -7,7 +7,7 @@ gem "rails", "<%= Rails::VERSION::STRING %>" ## Bundle edge rails: <%- if options.dev? -%> -gem "rails", "<%= Rails::VERSION::STRING %>", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" +gem "rails", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" <%- else -%> <%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> -- cgit v1.2.3 From cbb0b2f6f379df85959e95dce1e7b359197489c7 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:41:15 -0800 Subject: Simplify conditions for --dev and --edge --- railties/lib/generators/rails/app/templates/Gemfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 54aa53a181..2cc257fbd8 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -1,15 +1,15 @@ # Edit this Gemfile to bundle your application's dependencies. source 'http://gemcutter.org' -<% if !dev_or_edge? %> -gem "rails", "<%= Rails::VERSION::STRING %>" -<% end -%> - -## Bundle edge rails: <%- if options.dev? -%> gem "rails", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" +<%- elsif options.edge? -%> +gem "rails", :git => "git://github.com/rails/rails.git" <%- else -%> -<%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" +gem "rails", "<%= Rails::VERSION::STRING %>" + +# Bundle edge Rails instead +# gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> <% unless options[:skip_activerecord] -%> -- cgit v1.2.3 From 33a90f5079617f0b3422d24ef72e6c4d88552427 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:41:46 -0800 Subject: Not a fan of the double ## --- railties/lib/generators/rails/app/templates/Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 2cc257fbd8..3148269b6d 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -20,13 +20,13 @@ gem "rails", "<%= Rails::VERSION::STRING %>" gem "<%= gem_for_database %>"<% if require_for_database %>, :require => "<%= require_for_database %>"<% end %> <% end -%> -## Bundle the gems you use: +# Bundle the gems you use: # gem "bj" # gem "hpricot", "0.6" # gem "sqlite3-ruby", :require => "sqlite3" # gem "aws-s3", :require => "aws/s3" -## Bundle gems used only in certain environments: +# Bundle gems used only in certain environments: # gem "rspec", :group => :test # group :test do # gem "webrat" -- cgit v1.2.3 From c76df7a2d5b630adf52f89af01fe7fe8f097d199 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:45:26 -0800 Subject: Cleanup comments --- railties/lib/generators/rails/app/templates/Gemfile | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 3148269b6d..f89dbe1e63 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -1,4 +1,3 @@ -# Edit this Gemfile to bundle your application's dependencies. source 'http://gemcutter.org' <%- if options.dev? -%> @@ -8,25 +7,21 @@ gem "rails", :git => "git://github.com/rails/rails.git" <%- else -%> gem "rails", "<%= Rails::VERSION::STRING %>" -# Bundle edge Rails instead +# Bundle edge Rails instead: # gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> <% unless options[:skip_activerecord] -%> -<% if options[:database] == 'sqlite3' -%> -# ActiveRecord requires a database adapter. By default, -# Rails has selected sqlite3. -<% end -%> gem "<%= gem_for_database %>"<% if require_for_database %>, :require => "<%= require_for_database %>"<% end %> <% end -%> -# Bundle the gems you use: +# Bundle the extra gems: # gem "bj" # gem "hpricot", "0.6" # gem "sqlite3-ruby", :require => "sqlite3" # gem "aws-s3", :require => "aws/s3" -# Bundle gems used only in certain environments: +# Bundle gems for certain environments: # gem "rspec", :group => :test # group :test do # gem "webrat" -- cgit v1.2.3 From 59d8a2b4f5ffe97e01c4707278d47c29f1c66741 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 19:01:11 -0800 Subject: Lookup the status code and rework the Completed line a bit --- actionpack/lib/action_controller/railties/subscriber.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/actionpack/lib/action_controller/railties/subscriber.rb b/actionpack/lib/action_controller/railties/subscriber.rb index 1f0e6bf51a..4499e82292 100644 --- a/actionpack/lib/action_controller/railties/subscriber.rb +++ b/actionpack/lib/action_controller/railties/subscriber.rb @@ -15,9 +15,8 @@ module ActionController payload = event.payload additions = ActionController::Base.log_process_action(payload) - message = "Completed in %.0fms" % event.duration + message = "Completed #{payload[:status]} #{Rack::Utils::HTTP_STATUS_CODES[payload[:status]]} in %.0fms" % event.duration message << " (#{additions.join(" | ")})" unless additions.blank? - message << " with #{payload[:status]}" info(message) end -- cgit v1.2.3 From b392c818692b39b09836071a30e7a65034e752b5 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 5 Feb 2010 21:30:26 -0800 Subject: Fixes test fail --- railties/test/generators/app_generator_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 9c70dcbc92..54b970c0ab 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -158,7 +158,7 @@ class AppGeneratorTest < Rails::Generators::TestCase generator([destination_root], :dev => true).expects(:run).with("bundle install") silence(:stdout){ generator.invoke } rails_path = File.expand_path('../../..', Rails.root) - dev_gem = %(path #{rails_path.inspect}, :glob => "{*/,}*.gemspec") + dev_gem = %(gem "rails", :path => #{rails_path.inspect}) assert_file 'Gemfile', /^#{Regexp.escape(dev_gem)}$/ end -- cgit v1.2.3 From 5384df5589c7adccff845e943ce594f556397e77 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 5 Feb 2010 22:48:13 -0800 Subject: Updates subscriber test for new output --- actionpack/test/controller/subscriber_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/controller/subscriber_test.rb b/actionpack/test/controller/subscriber_test.rb index 119a18ebc5..d7c1166f14 100644 --- a/actionpack/test/controller/subscriber_test.rb +++ b/actionpack/test/controller/subscriber_test.rb @@ -73,7 +73,7 @@ class ACSubscriberTest < ActionController::TestCase wait assert_equal 2, logs.size assert_match /Completed/, logs.last - assert_match /with 200/, logs.last + assert_match /200 OK/, logs.last end def test_process_action_without_parameters -- cgit v1.2.3 From 4d177d46d95d77e06c88241c3bf809945fbd3a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 6 Feb 2010 11:39:51 +0100 Subject: Routes should not swallow all NameErrors [#3862 status:resolved]. --- actionpack/lib/action_dispatch/routing/route_set.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c49ac70562..dcf98b729b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -44,7 +44,8 @@ module ActionDispatch controller = "#{params[:controller].camelize}Controller" ActiveSupport::Inflector.constantize(controller) end - rescue NameError + rescue NameError => e + raise unless e.message.include?(controller) nil end -- cgit v1.2.3 From 22c0390085eed6fa2c4b78e1a9465ae3b7861568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 6 Feb 2010 11:52:28 +0100 Subject: Add a test which ensures namespaced roots. --- actionpack/test/dispatch/routing_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index dfe824fd70..bcb97e4ae0 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -118,6 +118,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest match 'description', :to => "account#description", :as => "description" resource :subscription, :credit, :credit_card + root :to => "account#index" + namespace :admin do resource :subscription end @@ -659,6 +661,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_namespaced_roots + with_test_routes do + assert_equal '/account', account_root_path + get '/account' + assert_equal 'account#index', @response.body + end + end + def test_optional_scoped_root with_test_routes do assert_equal '/en', root_path("en") -- cgit v1.2.3 From 95b63c6a078527b747c99ab1c881fdfe6577518b Mon Sep 17 00:00:00 2001 From: Henrik N Date: Sat, 6 Feb 2010 12:48:02 +0100 Subject: Fix 'rails server -h' double help banner. Correct its usage line. [#3874 status:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/lib/rails/commands/server.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index b21ae2a17b..c27214d3c8 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -9,6 +9,7 @@ module Rails options = {} args = args.dup opt_parser = OptionParser.new do |opts| + opts.banner = "Usage: rails server [options]" opts.on("-p", "--port=port", Integer, "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v } opts.on("-b", "--binding=ip", String, @@ -48,7 +49,9 @@ module Rails super ensure - puts 'Exiting' unless options[:daemonize] + # The '-h' option calls exit before @options is set. + # If we call 'options' with it unset, we get double help banners. + puts 'Exiting' unless @options && options[:daemonize] end def middleware -- cgit v1.2.3 From 1d9d9d2d89a90a85f27a1909e3c435c070bc1b40 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sat, 6 Feb 2010 21:36:46 +0700 Subject: Fix tiny version number from '3.0.0beta' to '3.0.0.beta1', so 'rake install' will be run correctly [#3879 status:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionmailer/lib/action_mailer/version.rb | 2 +- actionpack/lib/action_pack/version.rb | 2 +- activemodel/lib/active_model/version.rb | 2 +- activerecord/lib/active_record/version.rb | 2 +- activeresource/lib/active_resource/version.rb | 2 +- activesupport/lib/active_support/version.rb | 2 +- railties/lib/rails/version.rb | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/actionmailer/lib/action_mailer/version.rb b/actionmailer/lib/action_mailer/version.rb index b11c6ef055..56af531d01 100644 --- a/actionmailer/lib/action_mailer/version.rb +++ b/actionmailer/lib/action_mailer/version.rb @@ -2,7 +2,7 @@ module ActionMailer module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb index 4dde21dd40..67f89e1627 100644 --- a/actionpack/lib/action_pack/version.rb +++ b/actionpack/lib/action_pack/version.rb @@ -2,7 +2,7 @@ module ActionPack #:nodoc: module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb index f569447bc8..d51423ae1b 100644 --- a/activemodel/lib/active_model/version.rb +++ b/activemodel/lib/active_model/version.rb @@ -2,7 +2,7 @@ module ActiveModel module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb index d55b14f082..286ecd0289 100644 --- a/activerecord/lib/active_record/version.rb +++ b/activerecord/lib/active_record/version.rb @@ -2,7 +2,7 @@ module ActiveRecord module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/activeresource/lib/active_resource/version.rb b/activeresource/lib/active_resource/version.rb index 952a0d3b5f..461fef5283 100644 --- a/activeresource/lib/active_resource/version.rb +++ b/activeresource/lib/active_resource/version.rb @@ -2,7 +2,7 @@ module ActiveResource module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb index b92e469a08..6c6187be29 100644 --- a/activesupport/lib/active_support/version.rb +++ b/activesupport/lib/active_support/version.rb @@ -2,7 +2,7 @@ module ActiveSupport module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb index c327d4545a..d0c7cb45db 100644 --- a/railties/lib/rails/version.rb +++ b/railties/lib/rails/version.rb @@ -2,7 +2,7 @@ module Rails module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end -- cgit v1.2.3 From 6958eac1a00a4ab33e3facc70c80a07492288196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 6 Feb 2010 17:32:06 +0100 Subject: Add config.generators.templates to provide alternative paths for template lookup. --- railties/lib/rails/configuration.rb | 3 ++- railties/lib/rails/engine.rb | 4 ++++ railties/lib/rails/engine/configuration.rb | 1 + railties/lib/rails/generators.rb | 5 +++++ railties/lib/rails/generators/base.rb | 3 +-- railties/test/application/generators_test.rb | 15 ++++----------- railties/test/generators/generators_test_helper.rb | 1 + 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 7887a5d25f..50675d19b8 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -88,12 +88,13 @@ module Rails end class Generators #:nodoc: - attr_accessor :aliases, :options, :fallbacks, :colorize_logging + attr_accessor :aliases, :options, :templates, :fallbacks, :colorize_logging def initialize @aliases = Hash.new { |h,k| h[k] = {} } @options = Hash.new { |h,k| h[k] = {} } @fallbacks = {} + @templates = [] @colorize_logging = true end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 33d62c8155..5983a9ee6b 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -102,6 +102,10 @@ module Rails app.metal_loader.paths.unshift(*paths.app.metals.to_a) end + initializer :add_generator_templates do |app| + config.generators.templates.unshift(*paths.lib.templates.to_a) + end + initializer :load_application_initializers do paths.config.initializers.to_a.sort.each do |initializer| load(initializer) diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 7d6de91430..93b882f874 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -21,6 +21,7 @@ module Rails paths.app.views "app/views" paths.lib "lib", :load_path => true paths.lib.tasks "lib/tasks", :glob => "**/*.rake" + paths.lib.templates "lib/templates" paths.config "config" paths.config.initializers "config/initializers", :glob => "**/*.rb" paths.config.locales "config/locales", :glob => "*.{rb,yml}" diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 5d95f2fa52..5779357226 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -66,6 +66,11 @@ module Rails aliases.deep_merge! config.aliases options.deep_merge! config.options fallbacks.merge! config.fallbacks + templates_path.concat config.templates + end + + def self.templates_path + @templates_path ||= [] end def self.aliases #:nodoc: diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index dfa0d573c9..c801e2fec3 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -213,8 +213,7 @@ module Rails if base.name && base.name !~ /Base$/ Rails::Generators.subclasses << base - if defined?(Rails.root) && Rails.root - path = File.expand_path(File.join(Rails.root, 'lib', 'templates')) + Rails::Generators.templates_path.each do |path| if base.name.include?('::') base.source_paths << File.join(path, base.base_name, base.generator_name) else diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index 25fa100275..712c8bef36 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -52,30 +52,23 @@ module ApplicationTests end end - test "generators set rails fallbacks" do - with_config do |c| - c.generators.fallbacks[:shoulda] = :test_unit - expected = { :shoulda => :test_unit } - assert_equal expected, c.generators.fallbacks - end - end - - test "generators aliases, options and fallbacks on initialization" do + test "generators aliases, options, templates and fallbacks on initialization" do add_to_config <<-RUBY config.generators.rails :aliases => { :test_framework => "-w" } config.generators.orm :datamapper config.generators.test_framework :rspec config.generators.fallbacks[:shoulda] = :test_unit + config.generators.templates << "some/where" RUBY # Initialize the application require "#{app_path}/config/environment" require "rails/generators" - Rails::Generators.configure! assert_equal :rspec, Rails::Generators.options[:rails][:test_framework] assert_equal "-w", Rails::Generators.aliases[:rails][:test_framework] - assert_equal :test_unit, Rails::Generators.fallbacks[:shoulda] + assert_equal Hash[:shoulda => :test_unit], Rails::Generators.fallbacks + assert_equal ["#{app_path}/lib/templates", "some/where"], Rails::Generators.templates_path end test "generators no color on initialization" do diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index 3cd16a69f9..32be99b144 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -6,6 +6,7 @@ module Rails end end Rails.application.config.root = Rails.root +Rails.application.config.generators.templates = [File.join(Rails.root, "lib", "templates")] require 'rails/generators' require 'rails/generators/test_case' -- cgit v1.2.3 From 299ab1faa18f88e6f2b9a4724f9009109e86949e Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 6 Feb 2010 18:33:09 +0100 Subject: removes Kernel#daemonize, which is no longer used --- activesupport/lib/active_support/core_ext/kernel.rb | 1 - activesupport/lib/active_support/core_ext/kernel/daemonizing.rb | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 activesupport/lib/active_support/core_ext/kernel/daemonizing.rb diff --git a/activesupport/lib/active_support/core_ext/kernel.rb b/activesupport/lib/active_support/core_ext/kernel.rb index 1922d804bf..c3bed14f63 100644 --- a/activesupport/lib/active_support/core_ext/kernel.rb +++ b/activesupport/lib/active_support/core_ext/kernel.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/kernel/daemonizing' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/kernel/agnostics' require 'active_support/core_ext/kernel/requires' diff --git a/activesupport/lib/active_support/core_ext/kernel/daemonizing.rb b/activesupport/lib/active_support/core_ext/kernel/daemonizing.rb deleted file mode 100644 index ed9d1f9bf2..0000000000 --- a/activesupport/lib/active_support/core_ext/kernel/daemonizing.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Kernel - # Turns the current script into a daemon process that detaches from the console. - # It can be shut down with a TERM signal. - def daemonize - Process.daemon - end -end -- cgit v1.2.3 From bd5cb0562e93a1a0e225ee2bc9042c0e5bdb39dd Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 6 Feb 2010 18:35:44 +0100 Subject: rack debugger needs active_support/core_ext/kernel/requires for require_library_or_gem --- railties/lib/rails/rack/debugger.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb index 0a7b405553..93a743a747 100644 --- a/railties/lib/rails/rack/debugger.rb +++ b/railties/lib/rails/rack/debugger.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/kernel/requires' + module Rails module Rack class Debugger -- cgit v1.2.3 From f44a0b1d524064a2e919cd10d3013db680af9b17 Mon Sep 17 00:00:00 2001 From: RomD Date: Sat, 6 Feb 2010 17:18:10 +0100 Subject: fix usage examples and more to use new invocations Signed-off-by: Carl Lerche --- actionmailer/README | 2 +- actionmailer/lib/action_mailer/base.rb | 2 +- activerecord/lib/active_record/migration.rb | 4 +- .../lib/active_support/core_ext/kernel/debugger.rb | 2 +- activesupport/lib/active_support/whiny_nil.rb | 2 +- railties/README | 18 +++---- railties/guides/source/3_0_release_notes.textile | 6 +-- .../guides/source/action_mailer_basics.textile | 6 +-- .../source/active_support_core_extensions.textile | 2 +- .../activerecord_validations_callbacks.textile | 2 +- railties/guides/source/command_line.textile | 58 +++++++++++----------- .../source/debugging_rails_applications.textile | 12 ++--- railties/guides/source/generators.textile | 28 +++++------ railties/guides/source/getting_started.textile | 26 +++++----- railties/guides/source/migrations.textile | 10 ++-- railties/guides/source/performance_testing.textile | 16 +++--- railties/guides/source/plugins.textile | 28 +++++------ railties/guides/source/rails_on_rack.textile | 10 ++-- railties/guides/source/testing.textile | 8 +-- railties/lib/generators/rails/app/templates/README | 16 +++--- railties/lib/generators/rails/controller/USAGE | 2 +- railties/lib/generators/rails/generator/USAGE | 2 +- .../generators/rails/generator/templates/USAGE.tt | 2 +- railties/lib/generators/rails/helper/USAGE | 2 +- .../lib/generators/rails/integration_test/USAGE | 2 +- railties/lib/generators/rails/mailer/USAGE | 2 +- railties/lib/generators/rails/metal/USAGE | 2 +- railties/lib/generators/rails/migration/USAGE | 4 +- railties/lib/generators/rails/model/USAGE | 4 +- railties/lib/generators/rails/observer/USAGE | 2 +- .../lib/generators/rails/performance_test/USAGE | 2 +- railties/lib/generators/rails/plugin/USAGE | 2 +- railties/lib/generators/rails/resource/USAGE | 6 +-- railties/lib/generators/rails/scaffold/USAGE | 8 +-- .../lib/generators/rails/scaffold_controller/USAGE | 2 +- .../lib/generators/rails/session_migration/USAGE | 2 +- railties/lib/generators/rails/stylesheets/USAGE | 2 +- railties/lib/rails/commands/console.rb | 2 +- railties/lib/rails/commands/plugin.rb | 12 ++--- railties/lib/rails/generators/actions.rb | 4 +- railties/lib/rails/generators/base.rb | 8 +-- railties/lib/rails/rack/debugger.rb | 2 +- railties/test/generators/actions_test.rb | 10 ++-- railties/test/isolation/abstract_unit.rb | 2 +- 44 files changed, 173 insertions(+), 173 deletions(-) diff --git a/actionmailer/README b/actionmailer/README index e0e2ee436a..2a4d507d8a 100644 --- a/actionmailer/README +++ b/actionmailer/README @@ -101,7 +101,7 @@ Example: This Mailman can be the target for Postfix or other MTAs. In Rails, you would use the runner in the trivial case like this: - ./script/runner 'Mailman.receive(STDIN.read)' + rails runner 'Mailman.receive(STDIN.read)' However, invoking Rails in the runner for each mail to be received is very resource intensive. A single instance of Rails should be run within a daemon if it is going to be utilized to process more than just diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index ec85a20f70..4e89c1ea0c 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -9,7 +9,7 @@ module ActionMailer #:nodoc: # # To use Action Mailer, you need to create a mailer model. # - # $ script/generate mailer Notifier + # $ rails generate mailer Notifier # # The generated model inherits from ActionMailer::Base. Emails are defined by creating methods # within the model which are then used to set variables to be used in the mail template, to diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index c5630ba2fd..068d2a25b2 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -107,7 +107,7 @@ module ActiveRecord # The Rails package has several tools to help create and apply migrations. # # To generate a new migration, you can use - # script/generate migration MyNewMigration + # rails generate migration MyNewMigration # # where MyNewMigration is the name of your migration. The generator will # create an empty migration file timestamp_my_new_migration.rb in the db/migrate/ @@ -117,7 +117,7 @@ module ActiveRecord # MyNewMigration. # # There is a special syntactic shortcut to generate migrations that add fields to a table. - # script/generate migration add_fieldname_to_tablename fieldname:string + # rails generate migration add_fieldname_to_tablename fieldname:string # # This will generate the file timestamp_add_fieldname_to_tablename, which will look like this: # class AddFieldnameToTablename < ActiveRecord::Migration diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb index 59e03e3df7..22fcc1910b 100644 --- a/activesupport/lib/active_support/core_ext/kernel/debugger.rb +++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb @@ -1,6 +1,6 @@ module Kernel unless respond_to?(:debugger) - # Starts a debugging session if ruby-debug has been loaded (call script/server --debugger to do load it). + # Starts a debugging session if ruby-debug has been loaded (call rails server --debugger to do load it). def debugger message = "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n" defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message) diff --git a/activesupport/lib/active_support/whiny_nil.rb b/activesupport/lib/active_support/whiny_nil.rb index 4f6ff7d3b5..d600ea4825 100644 --- a/activesupport/lib/active_support/whiny_nil.rb +++ b/activesupport/lib/active_support/whiny_nil.rb @@ -11,7 +11,7 @@ # classes in NilClass::WHINERS the error message suggests which could be the # actual intended class: # -# $ script/runner nil.destroy +# $ rails runner nil.destroy # ... # You might have expected an instance of ActiveRecord::Base. # ... diff --git a/railties/README b/railties/README index 64dea89585..e4de4a5cb2 100644 --- a/railties/README +++ b/railties/README @@ -29,14 +29,14 @@ link:files/vendor/rails/actionpack/README.html. 1. At the command prompt, start a new Rails application using the rails command and your application name. Ex: rails myapp -2. Change directory into myapp and start the web server: script/server (run with --help for options) +2. Change directory into myapp and start the web server: rails server (run with --help for options) 3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!" 4. Follow the guidelines to start developing your application == Web Servers -By default, Rails will try to use Mongrel if it's installed when started with script/server, otherwise +By default, Rails will try to use Mongrel if it's installed when started with rails server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails with a variety of other web servers. @@ -45,7 +45,7 @@ suitable for development and deployment of Rails applications. If you have Ruby getting up and running with mongrel is as easy as: gem install mongrel. More info at: http://mongrel.rubyforge.org -Other ruby web servers exist which can run your rails application, however script/server does +Other ruby web servers exist which can run your rails application, however rails server does not search for them or start them. These include {Thin}[http://code.macournoyer.com/thin/], {Ebb}[http://ebb.rubyforge.org/], and Apache with {mod_rails}[http://www.modrails.com/]. For production use, often a web/proxy server such as {Apache}[http://apache.org], {Nginx}[http://nginx.net/], {LiteSpeed}[http://litespeedtech.com/], {Lighttpd}[http://www.lighttpd.net/] or {IIS}[http://www.iis.net/] is @@ -168,22 +168,22 @@ model. Here you'll have all parts of the application configured, just like it is application is running. You can inspect domain models, change values, and save to the database. Starting the script without arguments will launch it in the development environment. -To start the console, just run script/console from the application directory. +To start the console, just run rails console from the application directory. Options: * Passing the -s, --sandbox argument will rollback any modifications made to the database. * Passing an environment name as an argument will load the corresponding environment. - Example: script/console production. + Example: rails console production. More information about irb can be found at link:http://www.rubycentral.com/pickaxe/irb.html == dbconsole -You can go to the command line of your database directly through script/dbconsole. +You can go to the command line of your database directly through rails dbconsole. You would be connected to the database with the credentials defined in database.yml. Starting the script without arguments will connect you to the development database. Passing an -argument will connect you to a different database, like script/dbconsole production. +argument will connect you to a different database, like rails dbconsole production. Currently works for mysql, postgresql and sqlite. == Description of Contents @@ -250,7 +250,7 @@ app/views/layouts app/helpers Holds view helpers that should be named like weblogs_helper.rb. These are generated - for you automatically when using script/generate for controllers. Helpers can be used to + for you automatically when using rails generate for controllers. Helpers can be used to wrap functionality for your views into methods. config @@ -277,7 +277,7 @@ script Helper scripts for automation and generation. test - Unit and functional tests along with fixtures. When using the script/generate scripts, template + Unit and functional tests along with fixtures. When using the rails generate scripts, template test files will be generated for you and placed in this directory. vendor diff --git a/railties/guides/source/3_0_release_notes.textile b/railties/guides/source/3_0_release_notes.textile index 5e96f8cf06..1624172176 100644 --- a/railties/guides/source/3_0_release_notes.textile +++ b/railties/guides/source/3_0_release_notes.textile @@ -39,8 +39,8 @@ h4. script/* replaced by script/rails The new script/rails replaces all the scripts that used to be in the script directory. You do not run script/rails directly though, the +rails+ command detects it is being invoked in the root of a Rails application and runs the script for you. Intended usage is: -rails console # => ./script/console -rails g scaffold post title:string # => ./script/generate scaffold post title:string +rails console # => ./script/rails console +rails g scaffold post title:string # => ./script/rails generate scaffold post title:string Run rails --help for a list of all the options. @@ -557,4 +557,4 @@ h3. Credits See the "full list of contributors to Rails":http://contributors.rubyonrails.org/ for the many people who spent many hours making Rails 3. Kudos to all of them. -Rails 3.0 Release Notes were compiled by "Mikel Lindsaar":http://lindsaar.net. \ No newline at end of file +Rails 3.0 Release Notes were compiled by "Mikel Lindsaar":http://lindsaar.net. diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile index 2405b8f28c..941c2e9771 100644 --- a/railties/guides/source/action_mailer_basics.textile +++ b/railties/guides/source/action_mailer_basics.textile @@ -19,7 +19,7 @@ h4. Walkthrough to Generating a Mailer h5. Create the Mailer -./script/generate mailer UserMailer +rails generate mailer UserMailer create app/mailers/user_mailer.rb invoke erb create app/views/user_mailer @@ -111,7 +111,7 @@ Let's see how we would go about wiring it up using an observer. First off, we need to create a simple +User+ scaffold: -$ script/generate scaffold user name:string email:string login:string +$ rails generate scaffold user name:string email:string login:string $ rake db:migrate @@ -333,7 +333,7 @@ Receiving and parsing emails with Action Mailer can be a rather complex endeavou * Implement a +receive+ method in your mailer. -* Configure your email server to forward emails from the address(es) you would like your app to receive to +/path/to/app/script/runner 'UserMailer.receive(STDIN.read)'+. +* Configure your email server to forward emails from the address(es) you would like your app to receive to +/path/to/app/script/rails runner 'UserMailer.receive(STDIN.read)'+. Once a method called +receive+ is defined in any mailer, Action Mailer will parse the raw incoming email into an email object, decode it, instantiate a new mailer, and pass the email object to the mailer +receive+ instance method. Here's an example: diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 3073c3a7a5..bf39ed4c9f 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -1805,7 +1805,7 @@ Rails hijacks +LoadError.new+ to return a +MissingSourceFile+ exception: $ ruby -e 'require "nonexistent"' ...: no such file to load -- nonexistent (LoadError) ... -$ script/runner 'require "nonexistent"' +$ rails runner 'require "nonexistent"' ...: no such file to load -- nonexistent (MissingSourceFile) ... diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile index 9d0ee29ff2..dc61021f76 100644 --- a/railties/guides/source/activerecord_validations_callbacks.textile +++ b/railties/guides/source/activerecord_validations_callbacks.textile @@ -44,7 +44,7 @@ class Person < ActiveRecord::Base end -We can see how it works by looking at some script/console output: +We can see how it works by looking at some +rails console+ output: >> p = Person.new(:name => "John Doe") diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile index 1a571358a1..a84e928731 100644 --- a/railties/guides/source/command_line.textile +++ b/railties/guides/source/command_line.textile @@ -58,7 +58,7 @@ Without any prodding of any kind, +server+ will run our new shiny Rails app: $ cd commandsapp -$ ./script/server +$ rails server => Booting WEBrick... => Rails 2.2.0 application started on http://0.0.0.0:3000 => Ctrl-C to shutdown server; call with --help for options @@ -76,8 +76,8 @@ h4. +generate+ The +generate+ command uses templates to create a whole lot of things. You can always find out what's available by running +generate+ by itself. Let's do that: -$ ./script/generate -Usage: ./script/generate generator [options] [args] +$ rails generate +Usage: rails generate generator [options] [args] ... ... @@ -95,17 +95,17 @@ Using generators will save you a large amount of time by writing *boilerplate co Let's make our own controller with the controller generator. But what command should we use? Let's ask the generator: -INFO: All Rails console utilities have help text. As with most *NIX utilities, you can try adding +--help+ or +-h+ to the end, for example +./script/server --help+. +INFO: All Rails console utilities have help text. As with most *NIX utilities, you can try adding +--help+ or +-h+ to the end, for example +rails server --help+. -$ ./script/generate controller -Usage: ./script/generate controller ControllerName [options] +$ rails generate controller +Usage: rails generate controller ControllerName [options] ... ... Example: - ./script/generate controller CreditCard open debit credit close + rails generate controller CreditCard open debit credit close Credit card controller with URLs like /credit_card/debit. Controller: app/controllers/credit_card_controller.rb @@ -114,7 +114,7 @@ Example: Test: test/functional/credit_card_controller_test.rb Modules Example: - ./script/generate controller 'admin/credit_card' suspend late_fee + rails generate controller 'admin/credit_card' suspend late_fee Credit card admin controller with URLs /admin/credit_card/suspend. Controller: app/controllers/admin/credit_card_controller.rb @@ -126,7 +126,7 @@ Modules Example: Ah, the controller generator is expecting parameters in the form of +generate controller ControllerName action1 action2+. Let's make a +Greetings+ controller with an action of *hello*, which will say something nice to us. -$ ./script/generate controller Greetings hello +$ rails generate controller Greetings hello exists app/controllers/ exists app/helpers/ create app/views/greetings @@ -157,10 +157,10 @@ Then the view, to display our nice message (in +app/views/greetings/hello.html.e

<%= @message %>

-Deal. Go check it out in your browser. Fire up your server. Remember? +./script/server+ at the root of your Rails application should do it. +Deal. Go check it out in your browser. Fire up your server. Remember? +rails server+ at the root of your Rails application should do it. -$ ./script/server +$ rails server => Booting WEBrick... @@ -173,13 +173,13 @@ INFO: With a normal, plain-old Rails application, your URLs will generally follo "What about data, though?", you ask over a cup of coffee. Rails comes with a generator for data models too. Can you guess its generator name? -$ ./script/generate model -Usage: ./script/generate model ModelName [field:type, field:type] +$ rails generate model +Usage: rails generate model ModelName [field:type, field:type] ... Examples: - ./script/generate model account + rails generate model account creates an Account model, test, fixture, and migration: Model: app/models/account.rb @@ -187,7 +187,7 @@ Examples: Fixtures: test/fixtures/accounts.yml Migration: db/migrate/XXX_add_accounts.rb - ./script/generate model post title:string body:text published:boolean + rails generate model post title:string body:text published:boolean creates a Post model with a string title, text body, and published flag. @@ -197,7 +197,7 @@ But instead of generating a model directly (which we'll be doing later), let's s Let's set up a simple resource called "HighScore" that will keep track of our highest score on video games we play. -$ ./script/generate scaffold HighScore game:string score:integer +$ rails generate scaffold HighScore game:string score:integer exists app/models/ exists app/controllers/ exists app/helpers/ @@ -244,13 +244,13 @@ $ rake db:migrate INFO: Let's talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We'll make one in a moment. -Let's see the interface Rails created for us. ./script/server; http://localhost:3000/high_scores +Let's see the interface Rails created for us. rails server; http://localhost:3000/high_scores We can create new high scores (55,160 on Space Invaders!) h4. +console+ -The +console+ command lets you interact with your Rails application from the command line. On the underside, +script/console+ uses IRB, so if you've ever used it, you'll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website. +The +console+ command lets you interact with your Rails application from the command line. On the underside, +rails console+ uses IRB, so if you've ever used it, you'll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website. h4. +dbconsole+ @@ -265,7 +265,7 @@ Let's say you're creating a website for a client who wants a small accounting sy There is such a thing! The plugin we're installing is called "acts_as_paranoid", and it lets models implement a "deleted_at" column that gets set when you call destroy. Later, when calling find, the plugin will tack on a database check to filter out "deleted" things. -$ ./script/plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_paranoid +$ rails plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_paranoid + ./CHANGELOG + ./MIT-LICENSE ... @@ -277,7 +277,7 @@ h4. +runner+ runner runs Ruby code in the context of Rails non-interactively. For instance: -$ ./script/runner "Model.long_running_method" +$ rails runner "Model.long_running_method" h4. +destroy+ @@ -285,7 +285,7 @@ h4. +destroy+ Think of +destroy+ as the opposite of +generate+. It'll figure out what generate did, and undo it. Believe you-me, the creation of this tutorial used this command many times! -$ ./script/generate model Oops +$ rails generate model Oops exists app/models/ exists test/unit/ exists test/fixtures/ @@ -294,7 +294,7 @@ $ ./script/generate model Oops create test/fixtures/oops.yml exists db/migrate create db/migrate/20081221040817_create_oops.rb -$ ./script/destroy model Oops +$ rails destroy model Oops notempty db/migrate notempty db rm db/migrate/20081221040817_create_oops.rb @@ -314,7 +314,7 @@ h4. +about+ Check it: Version numbers for Ruby, RubyGems, Rails, the Rails subcomponents, your application's folder, the current Rails environment name, your app's database adapter, and schema version! +about+ is useful when you need to ask for help, check if a security patch might affect you, or when you need some stats for an existing Rails installation. -$ ./script/about +$ rails about About your application's environment Ruby version 1.8.6 (i486-linux) RubyGems version 1.3.1 @@ -399,7 +399,7 @@ Many people have created a large number different web servers in Ruby, and many NOTE: For more details on the Rack integration, see "Rails on Rack":rails_on_rack.html. -To use a different server, just install its gem, then use its name for the first parameter to +script/server+: +To use a different server, just install its gem, then use its name for the first parameter to +rails server+: $ sudo gem install mongrel @@ -412,9 +412,9 @@ Successfully installed mongrel-1.1.5 ... ... Installing RDoc documentation for mongrel-1.1.5... -$ script/server mongrel -=> Booting Mongrel (use 'script/server webrick' to force WEBrick) -=> Rails 2.2.0 application starting on http://0.0.0.0:3000 +$ rails server mongrel +=> Booting Mongrel (use 'rails server webrick' to force WEBrick) +=> Rails 3.0.0 application starting on http://0.0.0.0:3000 ... @@ -481,7 +481,7 @@ I got assigned some args: Then we'll make sure it got included in the list of available generators: -$ ./script/generate +$ rails generate ... ... Installed Generators @@ -491,7 +491,7 @@ Installed Generators SWEET! Now let's generate some text, yeah! -$ ./script/generate tutorial_test arg1 arg2 arg3 +$ rails generate tutorial_test arg1 arg2 arg3 exists public create public/tutorial.txt diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile index 94411a560e..cd0098d686 100644 --- a/railties/guides/source/debugging_rails_applications.textile +++ b/railties/guides/source/debugging_rails_applications.textile @@ -247,9 +247,9 @@ If you see the message in the console or logs: Make sure you have started your web server with the option +--debugger+: -~/PathTo/rails_project$ script/server --debugger -=> Booting Mongrel (use 'script/server webrick' to force WEBrick) -=> Rails 2.2.0 application starting on http://0.0.0.0:3000 +~/PathTo/rails_project$ rails server --debugger +=> Booting Mongrel (use 'rails server webrick' to force WEBrick) +=> Rails 3.0.0 application starting on http://0.0.0.0:3000 => Debugger enabled ... @@ -472,10 +472,10 @@ class Author < ActiveRecord::Base end -TIP: You can use ruby-debug while using script/console. Just remember to +require "ruby-debug"+ before calling the +debugger+ method. +TIP: You can use ruby-debug while using +rails console+. Just remember to +require "ruby-debug"+ before calling the +debugger+ method. -/PathTo/project $ script/console +/PathTo/project $ rails console Loading development environment (Rails 2.1.0) >> require "ruby-debug" => [] @@ -636,7 +636,7 @@ require 'bleak_house' if ENV['BLEAK_HOUSE'] Start a server instance with BleakHouse integration: -RAILS_ENV=production BLEAK_HOUSE=1 ruby-bleak-house ./script/server +RAILS_ENV=production BLEAK_HOUSE=1 ruby-bleak-house rails server Make sure to run a couple hundred requests to get better data samples, then press +CTRL-C+. The server will stop and Bleak House will produce a dumpfile in +/tmp+: diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile index fcd91f8956..4387fe3bd5 100644 --- a/railties/guides/source/generators.textile +++ b/railties/guides/source/generators.textile @@ -17,18 +17,18 @@ NOTE: This guide is about Rails generators for versions >= 3.0. Rails generators h3. First contact -When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +script/generate+: +When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +rails generate+: $ rails myapp $ cd myapp -$ ruby script/generate +$ rails generate You will get a list of all generators that comes with Rails. If you need a detailed description, for instance about the helper generator, you can simply do: -$ ruby script/generate helper --help +$ rails generate helper --help h3. Creating your first generator @@ -50,13 +50,13 @@ Our new generator is quite simple: it inherits from +Rails::Generators::Base+ an To invoke our new generator, we just need to do: -$ ruby script/generate initializer +$ rails generate initializer Before we go on, let's see our brand new generator description: -$ ruby script/generate initializer --help +$ rails generate initializer --help Rails usually is able to generate good descriptions if a generator is namespaced, as +ActiveRecord::Generators::ModelGenerator+, but not in this particular case. We can solve this problem in two ways. The first one is calling +desc+ inside our generator: @@ -77,7 +77,7 @@ h3. Creating generators with generators A faster way to create a generator is using the generator's generator: -$ ruby script/generate generator initializer +$ rails generate generator initializer create lib/generators/initializer create lib/generators/initializer/initializer_generator.rb create lib/generators/initializer/USAGE @@ -99,9 +99,9 @@ At first, we can notice that we are inheriting from +Rails::Generators::NamedBas We can see that by invoking the description of this new generator (don't forget to delete the old generator file): -$ ruby script/generate initializer --help +$ rails generate initializer --help Usage: - script/generate initializer NAME [options] + rails generate initializer NAME [options] We can also see in our new generator that it has a class method called +source_root+. This method points to where our generator templates will be placed and by default it points to the created directory under +RAILS_APP/lib/generators/initializer/templates+. In order to understand what a generator template means, let's create a file at +RAILS_APP/lib/generators/initializer/templates/initializer.rb+ with the following content: @@ -128,7 +128,7 @@ end And let's execute our generator: -$ ruby script/generate initializer foo +$ rails generate initializer foo We can see that now a initializer named foo was created at +config/initializers/foo.rb+ with the contents of our template. That means that copy_file copied a file in our source root to the destination path we gave. The method +file_name+ is automatically created when we inherit from +Rails::Generators::NamedBase+. @@ -166,7 +166,7 @@ end Before we customize our workflow, let's first see how our scaffold looks like: -$ ruby script/generate scaffold User name:string +$ rails generate scaffold User name:string invoke active_record create db/migrate/20091120125558_create_users.rb create app/models/user.rb @@ -212,7 +212,7 @@ If we generate another resource on scaffold, we can notice that neither styleshe To show that, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator: -$ ruby script/generate generator my_helper +$ rails generate generator my_helper After that, we can delete both templates directory and the +source_root+ class method from our new generators, because we are not going to need them. So our new generator looks like the following: @@ -232,7 +232,7 @@ end We can try out our new generator by creating a helper for users: -$ ruby script/generate my_helper users +$ rails generate my_helper users And it will generate the following helper file in app/helpers: @@ -258,7 +258,7 @@ end And see it in action when invoking generator once again: -$ ruby script/generate scaffold Post body:text +$ rails generate scaffold Post body:text [...] invoke my_helper create app/helpers/posts_helper.rb @@ -343,7 +343,7 @@ Rails::Generators.fallbacks[:shoulda] = :test_unit Now, if create a Comment scaffold, you will see that shoulda generators are being invoked, and at the end, they are just falling back to test unit generators: -$ ruby script/generate scaffold Comment body:text +$ rails generate scaffold Comment body:text invoke active_record create db/migrate/20091120151323_create_comments.rb create app/models/comment.rb diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index bd6dbda199..a6ac7f0f5b 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -258,10 +258,10 @@ h3. Hello, Rails! One of the traditional places to start with a new language is by getting some text up on screen quickly. To do that in Rails, you need to create at minimum a controller and a view. Fortunately, you can do that in a single command. Enter this command in your terminal: -$ script/generate controller home index +$ rails generate controller home index -TIP: If you're on Windows, or your Ruby is set up in some non-standard fashion, you may need to explicitly pass Rails +script+ commands to Ruby: +ruby script/generate controller home index+. +TIP: If you're on Windows, or your Ruby is set up in some non-standard fashion, you may need to explicitly pass Rails +script+ commands to Ruby: +rails generate controller home index+. Rails will create several files for you, including +app/views/home/index.html.erb+. This is the template that will be used to display the results of the +index+ action (method) in the +home+ controller. Open this file in your text editor and edit it to contain a single line of code: @@ -274,7 +274,7 @@ h4. Starting up the Web Server You actually have a functional Rails application already - after running only two commands! To see it, you need to start a web server on your development machine. You can do this by running another command: -$ script/server +$ rails server This will fire up an instance of the Mongrel web server by default (Rails can also use several other web servers). To see your application in action, open a browser window and navigate to +http://localhost:3000+. You should see Rails' default information page: @@ -323,7 +323,7 @@ h3. Creating a Resource In the case of the blog application, you can start by generating a scaffolded Post resource: this will represent a single blog posting. To do this, enter this command in your terminal: -$ script/generate scaffold Post name:string title:string content:text +$ rails generate scaffold Post name:string title:string content:text NOTE. While scaffolding will get you up and running quickly, the "one size fits all" code that it generates is unlikely to be a perfect fit for your application. In most cases, you'll need to customize the generated code. Many experienced Rails developers avoid scaffolding entirely, preferring to write all or most of their source code from scratch. @@ -349,7 +349,7 @@ The scaffold generator will build 14 files in your application, along with some h4. Running a Migration -One of the products of the +script/generate scaffold+ command is a _database migration_. Migrations are Ruby classes that are designed to make it simple to create and modify database tables. Rails uses rake commands to run migrations, and it's possible to undo a migration after it's been applied to your database. Migration filenames include a timestamp to ensure that they're processed in the order that they were created. +One of the products of the +rails generate scaffold+ command is a _database migration_. Migrations are Ruby classes that are designed to make it simple to create and modify database tables. Rails uses rake commands to run migrations, and it's possible to undo a migration after it's been applied to your database. Migration filenames include a timestamp to ensure that they're processed in the order that they were created. If you look in the +db/migrate/20090113124235_create_posts.rb+ file (remember, yours will have a slightly different name), here's what you'll find: @@ -400,7 +400,7 @@ Now you're ready to start working with posts. To do that, navigate to +http://lo !images/posts_index.png(Posts Index screenshot)! -This is the result of Rails rendering the +index+ view of your posts. There aren't currently any posts in the database, but if you click the +New Post+ link you can create one. After that, you'll find that you can edit posts, look at their details, or destroy them. All of the logic and HTML to handle this was built by the single +script/generate scaffold+ command. +This is the result of Rails rendering the +index+ view of your posts. There aren't currently any posts in the database, but if you click the +New Post+ link you can create one. After that, you'll find that you can edit posts, look at their details, or destroy them. All of the logic and HTML to handle this was built by the single +rails generate scaffold+ command. TIP: In development mode (which is what you're working in by default), Rails reloads your application with every browser request, so there's no need to stop and restart the web server. @@ -435,7 +435,7 @@ h4. Using the Console To see your validations in action, you can use the console. The console is a command-line tool that lets you execute Ruby code in the context of your application: -$ script/console +$ rails console After the console loads, you can use it to work with your application's models: @@ -516,7 +516,7 @@ TIP: For more details on the rendering process, see "Layouts and Rendering in Ra h4. Customizing the Layout -The view is only part of the story of how HTML is displayed in your web browser. Rails also has the concept of +layouts+, which are containers for views. When Rails renders a view to the browser, it does so by putting the view's HTML into a layout's HTML. The +script/generate scaffold+ command automatically created a default layout, +app/views/layouts/posts.html.erb+, for the posts. Open this layout in your editor and modify the +body+ tag: +The view is only part of the story of how HTML is displayed in your web browser. Rails also has the concept of +layouts+, which are containers for views. When Rails renders a view to the browser, it does so by putting the view's HTML into a layout's HTML. The +rails generate scaffold+ command automatically created a default layout, +app/views/layouts/posts.html.erb+, for the posts. Open this layout in your editor and modify the +body+ tag: -$ script/generate model Comment commenter:string body:text +$ rails generate model Comment commenter:string body:text post:references @@ -953,7 +953,7 @@ h4. Generating a Controller With the model in hand, you can turn your attention to creating a matching controller. Again, there's a generator for this: -$ script/generate controller Comments index show new edit +$ rails generate controller Comments index show new edit This creates eight files: @@ -967,7 +967,7 @@ This creates eight files: * +test/functional/comments_controller_test.rb+ - The functional tests for the controller * +test/unit/helpers/comments_helper_test.rb+ - The unit tests for the helper -The controller will be generated with empty methods and views for each action that you specified in the call to +script/generate controller+: +The controller will be generated with empty methods and views for each action that you specified in the call to +rails generate controller+: class CommentsController < ApplicationController @@ -1052,7 +1052,7 @@ This creates a new +Comment+ object _and_ sets up the +post_id+ field to have th h4. Building Views -Because you skipped scaffolding, you'll need to build views for comments "by hand". Invoking +script/generate controller+ will give you skeleton views, but they'll be devoid of actual content. Here's a first pass at fleshing out the comment views. +Because you skipped scaffolding, you'll need to build views for comments "by hand". Invoking +rails generate controller+ will give you skeleton views, but they'll be devoid of actual content. Here's a first pass at fleshing out the comment views. The +views/comments/index.html.erb+ view: @@ -1214,7 +1214,7 @@ h3. Building a Multi-Model Form Comments and posts are edited on two separate forms - which makes sense, given the flow of this mini-application. But what if you want to edit more than one thing on a single form? Rails 2.3 offers new support for nested forms. Let's add support for giving each post multiple tags, right in the form where you create the post. First, create a new model to hold the tags: -$ script/generate model tag name:string post:references +$ rails generate model tag name:string post:references Run the migration to create the database table: diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile index 771c3e2523..558cbb4771 100644 --- a/railties/guides/source/migrations.textile +++ b/railties/guides/source/migrations.textile @@ -105,7 +105,7 @@ h4. Creating a Model The model and scaffold generators will create migrations appropriate for adding a new model. This migration will already contain instructions for creating the relevant table. If you tell Rails what columns you want then statements for adding those will also be created. For example, running -ruby script/generate model Product name:string description:text +rails generate model Product name:string description:text will create a migration that looks like this @@ -135,7 +135,7 @@ h4. Creating a Standalone Migration If you are creating migrations for other purposes (for example to add a column to an existing table) then you can use the migration generator: -ruby script/generate migration AddPartNumberToProducts +rails generate migration AddPartNumberToProducts This will create an empty but appropriately named migration: @@ -153,7 +153,7 @@ end If the migration name is of the form "AddXXXToYYY" or "RemoveXXXFromYYY" and is followed by a list of column names and types then a migration containing the appropriate +add_column+ and +remove_column+ statements will be created. -ruby script/generate migration AddPartNumberToProducts part_number:string +rails generate migration AddPartNumberToProducts part_number:string will generate @@ -173,7 +173,7 @@ end Similarly, -ruby script/generate migration RemovePartNumberFromProducts part_number:string +rails generate migration RemovePartNumberFromProducts part_number:string generates @@ -193,7 +193,7 @@ end You are not limited to one magically generated column, for example -ruby script/generate migration AddDetailsToProducts part_number:string price:decimal +rails generate migration AddDetailsToProducts part_number:string price:decimal generates diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile index f0dc9acbb8..5c760a5966 100644 --- a/railties/guides/source/performance_testing.textile +++ b/railties/guides/source/performance_testing.textile @@ -37,7 +37,7 @@ h4. Generating Performance Tests Rails provides a generator called +performance_test+ for creating new performance tests: -script/generate performance_test homepage +rails generate performance_test homepage This generates +homepage_test.rb+ in the +test/performance+ directory: @@ -381,19 +381,19 @@ h4. +benchmarker+ Usage: -$ script/performance/benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ... +$ rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ... Examples: -$ script/performance/benchmarker 10 'Item.all' 'CouchItem.all' +$ rails benchmarker 10 'Item.all' 'CouchItem.all' If the +[times]+ argument is omitted, supplied methods are run just once: -$ script/performance/benchmarker 'Item.first' 'Item.last' +$ rails benchmarker 'Item.first' 'Item.last' h4. +profiler+ @@ -403,19 +403,19 @@ h4. +profiler+ Usage: -$ script/performance/profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html] +$ rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html] Examples: -$ script/performance/profiler 'Item.all' +$ rails profiler 'Item.all' This will profile +Item.all+ in +RubyProf::WALL_TIME+ measure mode. By default, it prints flat output to the shell. -$ script/performance/profiler 'Item.all' 10 graph +$ rails profiler 'Item.all' 10 graph This will profile +10.times { Item.all }+ with +RubyProf::WALL_TIME+ measure mode and print graph output to the shell. @@ -423,7 +423,7 @@ This will profile +10.times { Item.all }+ with +RubyProf::WALL_TIME+ measure mod If you want to store the output in a file: -$ script/performance/profiler 'Item.all' 10 graph 2> graph.txt +$ rails profiler 'Item.all' 10 graph 2> graph.txt h3. Helper Methods diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile index 06d0d493e4..71e1a7e3d3 100644 --- a/railties/guides/source/plugins.textile +++ b/railties/guides/source/plugins.textile @@ -39,9 +39,9 @@ The examples in this guide require that you have a working rails application. T gem install rails rails yaffle_guide cd yaffle_guide -script/generate scaffold bird name:string +rails generate scaffold bird name:string rake db:migrate -script/server +rails server Then navigate to http://localhost:3000/birds. Make sure you have a functioning rails app before continuing. @@ -57,16 +57,16 @@ This creates a plugin in 'vendor/plugins' including an 'init.rb' and 'README' as Examples:
-./script/generate plugin yaffle
-./script/generate plugin yaffle --with-generator
+rails generate plugin yaffle
+rails generate plugin yaffle --with-generator
 
-To get more detailed help on the plugin generator, type +./script/generate plugin+. +To get more detailed help on the plugin generator, type +rails generate plugin+. Later on this guide will describe how to work with generators, so go ahead and generate your plugin with the +--with-generator+ option now:
-./script/generate plugin yaffle --with-generator
+rails generate plugin yaffle --with-generator
 
You should see the following output: @@ -334,7 +334,7 @@ end To test that your method does what it says it does, run the unit tests with +rake+ from your plugin directory. To see this in action, fire up a console and start squawking: -$ ./script/console +$ rails console >> "Hello World".to_squawk => "squawk! Hello World" @@ -871,7 +871,7 @@ If you plan to distribute your plugin, developers will expect at least a minimum Rails ships with several built-in generators. You can see all of the generators available to you by typing the following at the command line: -./script/generate +rails generate You should see something like this: @@ -882,7 +882,7 @@ Installed Generators Builtin: controller, integration_test, mailer, migration, model, observer, plugin, resource, scaffold, session_migration
-When you run +script/generate yaffle_definition -h+ you should see the contents of your 'vendor/plugins/yaffle/generators/yaffle_definition/USAGE'. +When you run +rails generate yaffle_definition -h+ you should see the contents of your 'vendor/plugins/yaffle/generators/yaffle_definition/USAGE'. For this plugin, update the USAGE file could look like this: @@ -1111,11 +1111,11 @@ end To see this work, type: -./script/generate yaffle_route -./script/destroy yaffle_route +rails generate yaffle_route +rails destroy yaffle_route -NOTE: If you haven't set up the custom route from above, 'script/destroy' will fail and you'll have to remove it manually. +NOTE: If you haven't set up the custom route from above, 'rails destroy' will fail and you'll have to remove it manually. h3. Migrations @@ -1195,7 +1195,7 @@ h4. Generate Migrations Generating migrations has several advantages over other methods. Namely, you can allow other developers to more easily customize the migration. The flow looks like this: - * call your script/generate script and pass in whatever options they need + * call your rails generate script and pass in whatever options they need * examine the generated migration, adding/removing columns or other options as necessary This example will demonstrate how to use one of the built-in generator methods named 'migration_template' to create a migration file. Extending the rails migration generator requires a somewhat intimate knowledge of the migration generator internals, so it's best to write a test first: @@ -1289,7 +1289,7 @@ It's courteous to check to see if table names are being pluralized whenever you To run the generator, type the following at the command line: -./script/generate yaffle_migration bird +rails generate yaffle_migration bird and you will see a new file: diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile index df93580e89..eef44d9ec9 100644 --- a/railties/guides/source/rails_on_rack.textile +++ b/railties/guides/source/rails_on_rack.textile @@ -30,11 +30,11 @@ h4. Rails Application's Rack Object ActionController::Dispatcher.new is the primary Rack application object of a Rails application. Any Rack compliant web server should be using +ActionController::Dispatcher.new+ object to serve a Rails application.

-h4. +script/server+ +h4. +rails server+ -script/server does the basic job of creating a +Rack::Builder+ object and starting the webserver. This is Rails' equivalent of Rack's +rackup+ script. +rails server does the basic job of creating a +Rack::Builder+ object and starting the webserver. This is Rails' equivalent of Rack's +rackup+ script. -Here's how +script/server+ creates an instance of +Rack::Builder+ +Here's how +rails server+ creates an instance of +Rack::Builder+ app = Rack::Builder.new { @@ -54,7 +54,7 @@ Middlewares used in the code above are primarily useful only in the development h4. +rackup+ -To use +rackup+ instead of Rails' +script/server+, you can put the following inside +config.ru+ of your Rails application's root directory: +To use +rackup+ instead of Rails' +rails server+, you can put the following inside +config.ru+ of your Rails application's root directory: # RAILS_ROOT/config.ru @@ -233,7 +233,7 @@ h4. Generating a Metal Application Rails provides a generator called +metal+ for creating a new Metal application: -$ script/generate metal poller +$ rails generate metal poller This generates +poller.rb+ in the +app/metal+ directory: diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index c7b475899f..ac9fb4276e 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -56,7 +56,7 @@ h5. What are Fixtures? _Fixtures_ is a fancy word for sample data. Fixtures allow you to populate your testing database with predefined data before your tests run. Fixtures are database independent and assume one of two formats: *YAML* or *CSV*. In this guide we will use *YAML* which is the preferred format. -You'll find fixtures under your +test/fixtures+ directory. When you run +script/generate model+ to create a new model, fixture stubs will be automatically created and placed in this directory. +You'll find fixtures under your +test/fixtures+ directory. When you run +rails generate model+ to create a new model, fixture stubs will be automatically created and placed in this directory. h5. YAML @@ -144,10 +144,10 @@ For this guide we will be using Rails _scaffolding_. It will create the model, a NOTE: For more information on Rails _scaffolding_, refer to "Getting Started with Rails":getting_started.html -When you use +script/generate scaffold+, for a resource among other things it creates a test stub in the +test/unit+ folder: +When you use +rails generate scaffold+, for a resource among other things it creates a test stub in the +test/unit+ folder:
-$ script/generate scaffold post title:string body:text
+$ rails generate scaffold post title:string body:text
 ...
 create  app/models/post.rb
 create  test/unit/post_test.rb
@@ -604,7 +604,7 @@ Integration tests are used to test the interaction among any number of controlle
 Unlike Unit and Functional tests, integration tests have to be explicitly created under the 'test/integration' folder within your application. Rails provides a generator to create an integration test skeleton for you.
 
 
-$ script/generate integration_test user_flows
+$ rails generate integration_test user_flows
       exists  test/integration/
       create  test/integration/user_flows_test.rb
 
diff --git a/railties/lib/generators/rails/app/templates/README b/railties/lib/generators/rails/app/templates/README
index 37ec8ea211..b175146797 100644
--- a/railties/lib/generators/rails/app/templates/README
+++ b/railties/lib/generators/rails/app/templates/README
@@ -29,14 +29,14 @@ link:files/vendor/rails/actionpack/README.html.
 
 1. At the command prompt, start a new Rails application using the rails command
    and your application name. Ex: rails myapp
-2. Change directory into myapp and start the web server: script/server (run with --help for options)
+2. Change directory into myapp and start the web server: rails server (run with --help for options)
 3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!"
 4. Follow the guidelines to start developing your application
 
 
 == Web Servers
 
-By default, Rails will try to use Mongrel if it's are installed when started with script/server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails
+By default, Rails will try to use Mongrel if it's are installed when started with rails server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails
 with a variety of other web servers.
 
 Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is
@@ -164,20 +164,20 @@ Finally, when you're ready to resume execution, you enter "cont"
 
 == Console
 
-You can interact with the domain model by starting the console through script/console.
+You can interact with the domain model by starting the console through rails console.
 Here you'll have all parts of the application configured, just like it is when the
 application is running. You can inspect domain models, change values, and save to the
 database. Starting the script without arguments will launch it in the development environment.
-Passing an argument will specify a different environment, like script/console production.
+Passing an argument will specify a different environment, like rails console production.
 
 To reload your controllers and models after launching the console run reload!
 
 == dbconsole
 
-You can go to the command line of your database directly through script/dbconsole.
+You can go to the command line of your database directly through rails dbconsole.
 You would be connected to the database with the credentials defined in database.yml.
 Starting the script without arguments will connect you to the development database. Passing an
-argument will connect you to a different database, like script/dbconsole production.
+argument will connect you to a different database, like rails dbconsole production.
 Currently works for mysql, postgresql and sqlite.
 
 == Description of Contents
@@ -207,7 +207,7 @@ app/views/layouts
 
 app/helpers
   Holds view helpers that should be named like weblogs_helper.rb. These are generated
-  for you automatically when using script/generate for controllers. Helpers can be used to
+  for you automatically when using rails generate for controllers. Helpers can be used to
   wrap functionality for your views into methods.
 
 config
@@ -234,7 +234,7 @@ script
   Helper scripts for automation and generation.
 
 test
-  Unit and functional tests along with fixtures. When using the script/generate scripts, template
+  Unit and functional tests along with fixtures. When using the rails generate scripts, template
   test files will be generated for you and placed in this directory.
 
 vendor
diff --git a/railties/lib/generators/rails/controller/USAGE b/railties/lib/generators/rails/controller/USAGE
index 6ed4b2edfc..70618a3906 100644
--- a/railties/lib/generators/rails/controller/USAGE
+++ b/railties/lib/generators/rails/controller/USAGE
@@ -9,7 +9,7 @@ Description:
     template engine and test framework generators.
 
 Example:
-    `./script/generate controller CreditCard open debit credit close`
+    `rails generate controller CreditCard open debit credit close`
 
     Credit card controller with URLs like /credit_card/debit.
         Controller:      app/controllers/credit_card_controller.rb
diff --git a/railties/lib/generators/rails/generator/USAGE b/railties/lib/generators/rails/generator/USAGE
index ca7d3f62d0..d8c3f7f634 100644
--- a/railties/lib/generators/rails/generator/USAGE
+++ b/railties/lib/generators/rails/generator/USAGE
@@ -3,7 +3,7 @@ Description:
     CamelCased or under_scored, as an argument. 
 
 Example:
-    `./script/generate generator Awesome`
+    `rails generate generator Awesome`
 
     creates a standard awesome generator:
         lib/generators/awesome/
diff --git a/railties/lib/generators/rails/generator/templates/USAGE.tt b/railties/lib/generators/rails/generator/templates/USAGE.tt
index ea9f4f12cc..1bb8df840d 100644
--- a/railties/lib/generators/rails/generator/templates/USAGE.tt
+++ b/railties/lib/generators/rails/generator/templates/USAGE.tt
@@ -2,7 +2,7 @@ Description:
     Explain the generator
 
 Example:
-    ./script/generate <%= file_name %> Thing
+    rails generate <%= file_name %> Thing
 
     This will create:
         what/will/it/create
diff --git a/railties/lib/generators/rails/helper/USAGE b/railties/lib/generators/rails/helper/USAGE
index 531c9b390a..c0ddb0f606 100644
--- a/railties/lib/generators/rails/helper/USAGE
+++ b/railties/lib/generators/rails/helper/USAGE
@@ -9,7 +9,7 @@ Description:
     test framework.
 
 Example:
-    `./script/generate helper CreditCard`
+    `rails generate helper CreditCard`
 
     Credit card helper.
         Helper:     app/helpers/credit_card_helper.rb
diff --git a/railties/lib/generators/rails/integration_test/USAGE b/railties/lib/generators/rails/integration_test/USAGE
index b76c35a702..57ee3543e6 100644
--- a/railties/lib/generators/rails/integration_test/USAGE
+++ b/railties/lib/generators/rails/integration_test/USAGE
@@ -6,5 +6,5 @@ Description:
     TestUnit.
 
 Example:
-    `./script/generate integration_test GeneralStories` creates a GeneralStories
+    `rails generate integration_test GeneralStories` creates a GeneralStories
     integration test in test/integration/general_stories_test.rb
diff --git a/railties/lib/generators/rails/mailer/USAGE b/railties/lib/generators/rails/mailer/USAGE
index beae79fbf4..a08d459739 100644
--- a/railties/lib/generators/rails/mailer/USAGE
+++ b/railties/lib/generators/rails/mailer/USAGE
@@ -6,7 +6,7 @@ Description:
     engine and test framework generators.
 
 Example:
-    `./script/generate mailer Notifications signup forgot_password invoice`
+    `rails generate mailer Notifications signup forgot_password invoice`
 
     creates a Notifications mailer class, views, test, and fixtures:
         Mailer:     app/mailers/notifications.rb
diff --git a/railties/lib/generators/rails/metal/USAGE b/railties/lib/generators/rails/metal/USAGE
index 123ec6c03f..c88325a444 100644
--- a/railties/lib/generators/rails/metal/USAGE
+++ b/railties/lib/generators/rails/metal/USAGE
@@ -2,7 +2,7 @@ Description:
     Cast some metal!
 
 Examples:
-    `./script/generate metal poller`
+    `rails generate metal poller`
 
         This will create:
             Metal: app/metal/poller.rb
diff --git a/railties/lib/generators/rails/migration/USAGE b/railties/lib/generators/rails/migration/USAGE
index d91127aac3..d21c81b760 100644
--- a/railties/lib/generators/rails/migration/USAGE
+++ b/railties/lib/generators/rails/migration/USAGE
@@ -8,12 +8,12 @@ Description:
     column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
 
 Example:
-    `./script/generate migration AddSslFlag`
+    `rails generate migration AddSslFlag`
 
     If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
     db/migrate/20080514090912_add_ssl_flag.rb
 
-    `./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`
+    `rails generate migration AddTitleBodyToPost title:string body:text published:boolean`
 
     This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with
     this in the Up migration:
diff --git a/railties/lib/generators/rails/model/USAGE b/railties/lib/generators/rails/model/USAGE
index b056d5df8b..d97e9ac103 100644
--- a/railties/lib/generators/rails/model/USAGE
+++ b/railties/lib/generators/rails/model/USAGE
@@ -16,7 +16,7 @@ Description:
     created model. This allows you create Single Table Inheritance models.
 
 Examples:
-    `./script/generate model account`
+    `rails generate model account`
 
         For ActiveRecord and TestUnit it creates:
 
@@ -25,6 +25,6 @@ Examples:
             Fixtures:   test/fixtures/accounts.yml
             Migration:  db/migrate/XXX_add_accounts.rb
 
-    `./script/generate model post title:string body:text published:boolean`
+    `rails generate model post title:string body:text published:boolean`
 
         Creates a Post model with a string title, text body, and published flag.
diff --git a/railties/lib/generators/rails/observer/USAGE b/railties/lib/generators/rails/observer/USAGE
index 9a20f55a89..d8f32a6a48 100644
--- a/railties/lib/generators/rails/observer/USAGE
+++ b/railties/lib/generators/rails/observer/USAGE
@@ -5,7 +5,7 @@ Description:
     This generator only invokes your ORM and test framework generators.
 
 Example:
-    `./script/generate observer Account`
+    `rails generate observer Account`
 
     For ActiveRecord and TestUnit it creates:
         Observer:   app/models/account_observer.rb
diff --git a/railties/lib/generators/rails/performance_test/USAGE b/railties/lib/generators/rails/performance_test/USAGE
index ee82578cdb..9dc799559c 100644
--- a/railties/lib/generators/rails/performance_test/USAGE
+++ b/railties/lib/generators/rails/performance_test/USAGE
@@ -6,5 +6,5 @@ Description:
     TestUnit.
 
 Example:
-    `./script/generate performance_test GeneralStories` creates a GeneralStories
+    `rails generate performance_test GeneralStories` creates a GeneralStories
     performance test in test/performance/general_stories_test.rb
diff --git a/railties/lib/generators/rails/plugin/USAGE b/railties/lib/generators/rails/plugin/USAGE
index 8a17fa4dec..00a429c585 100644
--- a/railties/lib/generators/rails/plugin/USAGE
+++ b/railties/lib/generators/rails/plugin/USAGE
@@ -3,7 +3,7 @@ Description:
     CamelCased or under_scored, as an argument. 
 
 Example:
-    `./script/generate plugin BrowserFilters`
+    `rails generate plugin BrowserFilters`
 
     creates a standard browser_filters plugin:
         vendor/plugins/browser_filters/README
diff --git a/railties/lib/generators/rails/resource/USAGE b/railties/lib/generators/rails/resource/USAGE
index 936619b0db..e359cd574f 100644
--- a/railties/lib/generators/rails/resource/USAGE
+++ b/railties/lib/generators/rails/resource/USAGE
@@ -18,6 +18,6 @@ Description:
     views or add any methods to the generated controller.
 
 Examples:
-    `./script/generate resource post` # no attributes
-    `./script/generate resource post title:string body:text published:boolean`
-    `./script/generate resource purchase order_id:integer amount:decimal`
+    `rails generate resource post` # no attributes
+    `rails generate resource post title:string body:text published:boolean`
+    `rails generate resource purchase order_id:integer amount:decimal`
diff --git a/railties/lib/generators/rails/scaffold/USAGE b/railties/lib/generators/rails/scaffold/USAGE
index 530ccdaf0a..be1d113ed8 100644
--- a/railties/lib/generators/rails/scaffold/USAGE
+++ b/railties/lib/generators/rails/scaffold/USAGE
@@ -21,9 +21,9 @@ Description:
     declaration in config/routes.rb.
 
     If you want to remove all the generated files, run
-    'script/destroy scaffold ModelName'.
+    'rails destroy scaffold ModelName'.
 
 Examples:
-    `./script/generate scaffold post`
-    `./script/generate scaffold post title:string body:text published:boolean`
-    `./script/generate scaffold purchase order_id:integer amount:decimal`
+    `rails generate scaffold post`
+    `rails generate scaffold post title:string body:text published:boolean`
+    `rails generate scaffold purchase order_id:integer amount:decimal`
diff --git a/railties/lib/generators/rails/scaffold_controller/USAGE b/railties/lib/generators/rails/scaffold_controller/USAGE
index d60a3c3680..673f69bc81 100644
--- a/railties/lib/generators/rails/scaffold_controller/USAGE
+++ b/railties/lib/generators/rails/scaffold_controller/USAGE
@@ -11,7 +11,7 @@ Description:
     template engine and test framework generators.
 
 Example:
-    `./script/generate scaffold_controller CreditCard`
+    `rails generate scaffold_controller CreditCard`
 
     Credit card controller with URLs like /credit_card/debit.
         Controller:      app/controllers/credit_cards_controller.rb
diff --git a/railties/lib/generators/rails/session_migration/USAGE b/railties/lib/generators/rails/session_migration/USAGE
index e106f6ecc8..564d1ffd78 100644
--- a/railties/lib/generators/rails/session_migration/USAGE
+++ b/railties/lib/generators/rails/session_migration/USAGE
@@ -5,4 +5,4 @@ Description:
     Before invoking this generator, be sure that your ORM supports session stores.
 
 Example:
-    `./script/generate session_migration CreateSessionTable`
+    `rails generate session_migration CreateSessionTable`
diff --git a/railties/lib/generators/rails/stylesheets/USAGE b/railties/lib/generators/rails/stylesheets/USAGE
index d6a81e51d0..59e5495d0b 100644
--- a/railties/lib/generators/rails/stylesheets/USAGE
+++ b/railties/lib/generators/rails/stylesheets/USAGE
@@ -2,4 +2,4 @@ Description:
     Copies scaffold stylesheets to public/stylesheets/.
 
 Examples:
-    `./script/generate stylesheets`
+    `rails generate stylesheets`
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
index a984eff6e2..3fa4c939a8 100644
--- a/railties/lib/rails/commands/console.rb
+++ b/railties/lib/rails/commands/console.rb
@@ -19,7 +19,7 @@ module Rails
         opt.banner = "Usage: console [environment] [options]"
         opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
         opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
-        opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/console` instead' }
+        opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/rails console` instead' }
         opt.parse!(ARGV)
       end
 
diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb
index af12df1425..8bcd92a33b 100644
--- a/railties/lib/rails/commands/plugin.rb
+++ b/railties/lib/rails/commands/plugin.rb
@@ -2,7 +2,7 @@
 #
 # Installing plugins:
 #
-#   $ ./script/plugin install continuous_builder asset_timestamping
+#   $ rails plugin install continuous_builder asset_timestamping
 # 
 # Specifying revisions:
 #
@@ -319,13 +319,13 @@ module Commands
         o.separator ""
         o.separator "EXAMPLES"
         o.separator "  Install a plugin:"
-        o.separator "    #{@script_name} install continuous_builder\n"
+        o.separator "    #{@script_name} plugin install continuous_builder\n"
         o.separator "  Install a plugin from a subversion URL:"
-        o.separator "    #{@script_name} install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n"
+        o.separator "    #{@script_name} plugin install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n"
         o.separator "  Install a plugin from a git URL:"
-        o.separator "    #{@script_name} install git://github.com/SomeGuy/my_awesome_plugin.git\n"
+        o.separator "    #{@script_name} plugin install git://github.com/SomeGuy/my_awesome_plugin.git\n"
         o.separator "  Install a plugin and add a svn:externals entry to vendor/plugins"
-        o.separator "    #{@script_name} install -x continuous_builder\n"
+        o.separator "    #{@script_name} plugin install -x continuous_builder\n"
       end
     end
     
@@ -381,7 +381,7 @@ module Commands
                       "Exports the plugin, allowing you to check it into your local repository. Does not enable updates, or add an svn:externals entry.") { |v| @method = :export }
         o.on(         "-q", "--quiet",
                       "Suppresses the output from installation.",
-                      "Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true }
+                      "Ignored if -v is passed (rails plugin -v install ...)") { |v| @options[:quiet] = true }
         o.on(         "-r REVISION", "--revision REVISION",
                       "Checks out the given revision from subversion or git.",
                       "Ignored if subversion/git is not used.") { |v| @options[:revision] = v }
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index f95b15acce..247a141943 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -32,7 +32,7 @@ module Rails
           options[:git] = "-b #{options[:branch]} #{options[:git]}"   if options[:branch]
           options[:svn] = "-r #{options[:revision]} #{options[:svn]}" if options[:revision]
           in_root do
-            run_ruby_script "script/plugin install #{options[:svn] || options[:git]}", :verbose => false
+            run_ruby_script "script/rails plugin install #{options[:svn] || options[:git]}", :verbose => false
           end
         else
           log "! no git or svn provided for #{name}. Skipping..."
@@ -226,7 +226,7 @@ module Rails
         log :generate, what
         argument = args.map {|arg| arg.to_s }.flatten.join(" ")
 
-        in_root { run_ruby_script("script/generate #{what} #{argument}", :verbose => false) }
+        in_root { run_ruby_script("script/rails generate #{what} #{argument}", :verbose => false) }
       end
 
       # Runs the supplied rake task
diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb
index c801e2fec3..9624c35c0b 100644
--- a/railties/lib/rails/generators/base.rb
+++ b/railties/lib/rails/generators/base.rb
@@ -62,7 +62,7 @@ module Rails
       #
       # For example, if the user invoke the controller generator as:
       #
-      #   ruby script/generate controller Account --test-framework=test_unit
+      #   rails generate controller Account --test-framework=test_unit
       #
       # The controller generator will then try to invoke the following generators:
       #
@@ -117,11 +117,11 @@ module Rails
       # All hooks come with switches for user interface. If the user don't want
       # to use any test framework, he can do:
       #
-      #   ruby script/generate controller Account --skip-test-framework
+      #   rails generate controller Account --skip-test-framework
       #
       # Or similarly:
       #
-      #   ruby script/generate controller Account --no-test-framework
+      #   rails generate controller Account --no-test-framework
       #
       # ==== Boolean hooks
       #
@@ -133,7 +133,7 @@ module Rails
       #
       # Then, if you want, webrat to be invoked, just supply:
       #
-      #   ruby script/generate controller Account --webrat
+      #   rails generate controller Account --webrat
       #
       # The hooks lookup is similar as above:
       #
diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb
index 0a7b405553..c0448f65e6 100644
--- a/railties/lib/rails/rack/debugger.rb
+++ b/railties/lib/rails/rack/debugger.rb
@@ -4,7 +4,7 @@ module Rails
       def initialize(app)
         @app = app
 
-        ARGV.clear # clear ARGV so that script/server options aren't passed to IRB
+        ARGV.clear # clear ARGV so that rails server options aren't passed to IRB
 
         require_library_or_gem 'ruby-debug'
         ::Debugger.start
diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb
index cb1fa96e0d..0512f69f4a 100644
--- a/railties/test/generators/actions_test.rb
+++ b/railties/test/generators/actions_test.rb
@@ -36,22 +36,22 @@ class ActionsTest < Rails::Generators::TestCase
   end
 
   def test_plugin_with_git_option_should_run_plugin_install
-    generator.expects(:run_ruby_script).once.with("script/plugin install #{@git_plugin_uri}", :verbose => false)
+    generator.expects(:run_ruby_script).once.with("script/rails plugin install #{@git_plugin_uri}", :verbose => false)
     action :plugin, 'restful-authentication', :git => @git_plugin_uri
   end
 
   def test_plugin_with_svn_option_should_run_plugin_install
-    generator.expects(:run_ruby_script).once.with("script/plugin install #{@svn_plugin_uri}", :verbose => false)
+    generator.expects(:run_ruby_script).once.with("script/rails plugin install #{@svn_plugin_uri}", :verbose => false)
     action :plugin, 'restful-authentication', :svn => @svn_plugin_uri
   end
 
   def test_plugin_with_git_option_and_branch_should_run_plugin_install
-    generator.expects(:run_ruby_script).once.with("script/plugin install -b stable #{@git_plugin_uri}", :verbose => false)
+    generator.expects(:run_ruby_script).once.with("script/rails plugin install -b stable #{@git_plugin_uri}", :verbose => false)
     action :plugin, 'restful-authentication', :git => @git_plugin_uri, :branch => 'stable'
   end
 
   def test_plugin_with_svn_option_and_revision_should_run_plugin_install
-    generator.expects(:run_ruby_script).once.with("script/plugin install -r 1234 #{@svn_plugin_uri}", :verbose => false)
+    generator.expects(:run_ruby_script).once.with("script/rails plugin install -r 1234 #{@svn_plugin_uri}", :verbose => false)
     action :plugin, 'restful-authentication', :svn => @svn_plugin_uri, :revision => 1234
   end
 
@@ -155,7 +155,7 @@ class ActionsTest < Rails::Generators::TestCase
   end
 
   def test_generate_should_run_script_generate_with_argument_and_options
-    generator.expects(:run_ruby_script).once.with('script/generate model MyModel', :verbose => false)
+    generator.expects(:run_ruby_script).once.with('script/rails generate model MyModel', :verbose => false)
     action :generate, 'model', 'MyModel'
   end
 
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index dcadf3f485..364dbd8e55 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -154,7 +154,7 @@ module TestHelpers
 
     def script(script)
       Dir.chdir(app_path) do
-        `#{Gem.ruby} #{app_path}/script/#{script}`
+        `#{Gem.ruby} #{app_path}/script/rails #{script}`
       end
     end
 
-- 
cgit v1.2.3


From 3caca406c8cadbd4a42e50bfbb3e2794fd8d985e Mon Sep 17 00:00:00 2001
From: RomD 
Date: Sat, 6 Feb 2010 17:21:05 +0100
Subject: remove trailing whitespace

Signed-off-by: Carl Lerche 
---
 activesupport/lib/active_support/whiny_nil.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/activesupport/lib/active_support/whiny_nil.rb b/activesupport/lib/active_support/whiny_nil.rb
index d600ea4825..11b05efac1 100644
--- a/activesupport/lib/active_support/whiny_nil.rb
+++ b/activesupport/lib/active_support/whiny_nil.rb
@@ -11,7 +11,7 @@
 # classes in NilClass::WHINERS the error message suggests which could be the
 # actual intended class:
 #
-#   $ rails runner nil.destroy 
+#   $ rails runner nil.destroy
 #   ...
 #   You might have expected an instance of ActiveRecord::Base.
 #   ...
-- 
cgit v1.2.3


From 28fe0c330a2081b1709522274c0b1b193e50ee20 Mon Sep 17 00:00:00 2001
From: David Heinemeier Hansson 
Date: Sat, 6 Feb 2010 13:20:47 -0800
Subject: Silenced "SHOW FIELDS" and "SET SQL_AUTO_IS_NULL=0" statements from
 the MySQL driver to improve log signal to noise ration in development [DHH]

---
 activerecord/CHANGELOG                                       |  5 +++++
 .../lib/active_record/connection_adapters/mysql_adapter.rb   | 12 ++++++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index a4fa000964..214ec8c1d8 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,10 @@
 *Edge*
 
+* Silenced "SHOW FIELDS" and "SET SQL_AUTO_IS_NULL=0" statements from the MySQL driver to improve log signal to noise ration in development [DHH]
+
+
+*Rails 3.0 [Beta] (February 4th, 2010)*
+
 * PostgreSQLAdapter: set time_zone to UTC when Base.default_timezone == :utc so that Postgres doesn't incorrectly offset-adjust values inserted into TIMESTAMP WITH TIME ZONE columns. #3777 [Jack Christensen]
 
 * Allow relations to be used as scope.
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 8c0bf6396a..1f1df7e8c3 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -321,7 +321,11 @@ module ActiveRecord
 
       # Executes a SQL query and returns a MySQL::Result object. Note that you have to free the Result object after you're done using it.
       def execute(sql, name = nil) #:nodoc:
-        log(sql, name) { @connection.query(sql) }
+        if name == :skip_logging
+          @connection.query(sql)
+        else
+          log(sql, name) { @connection.query(sql) }
+        end
       rescue ActiveRecord::StatementInvalid => exception
         if exception.message.split(":").first =~ /Packets out of order/
           raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information.  If you're on Windows, use the Instant Rails installer to get the updated mysql bindings."
@@ -456,7 +460,7 @@ module ActiveRecord
       def columns(table_name, name = nil)#:nodoc:
         sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}"
         columns = []
-        result = execute(sql, name)
+        result = execute(sql, :skip_logging)
         result.each { |field| columns << MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") }
         result.free
         columns
@@ -616,11 +620,11 @@ module ActiveRecord
 
         def configure_connection
           encoding = @config[:encoding]
-          execute("SET NAMES '#{encoding}'") if encoding
+          execute("SET NAMES '#{encoding}'", :skip_logging) if encoding
 
           # By default, MySQL 'where id is null' selects the last inserted id.
           # Turn this off. http://dev.rubyonrails.org/ticket/6778
-          execute("SET SQL_AUTO_IS_NULL=0")
+          execute("SET SQL_AUTO_IS_NULL=0", :skip_logging)
         end
 
         def select(sql, name = nil)
-- 
cgit v1.2.3


From 9f3ea4505acccaa1bf6ded0a24b4c2aa7e2b7cab Mon Sep 17 00:00:00 2001
From: Jeremy Kemper 
Date: Sat, 6 Feb 2010 21:14:29 -0800
Subject: CI: set env after sudo

---
 ci/ci_build.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ci/ci_build.rb b/ci/ci_build.rb
index 4c3a894b47..ac0dbb1dc1 100755
--- a/ci/ci_build.rb
+++ b/ci/ci_build.rb
@@ -33,7 +33,7 @@ cd root_dir do
   puts
   puts "[CruiseControl] Bundling RubyGems"
   puts
-  build_results[:bundle] = system 'env CI=1 sudo bundle install'
+  build_results[:bundle] = system 'sudo env CI=1 bundle install'
 end
 
 cd "#{root_dir}/activesupport" do
-- 
cgit v1.2.3


From 03b192d1b4adec24caa4c345d868bcc8d18540b2 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper 
Date: Sat, 6 Feb 2010 21:18:08 -0800
Subject: CI: sudo unnecessary. Bump bundler dep to 0.9.3.

---
 ci/ci_build.rb | 4 ++--
 rails.gemspec  | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/ci/ci_build.rb b/ci/ci_build.rb
index ac0dbb1dc1..a227902032 100755
--- a/ci/ci_build.rb
+++ b/ci/ci_build.rb
@@ -25,7 +25,7 @@ puts "Running command: #{rubygems_install_cmd}"
 build_results[:install_rubygems_update] = system rubygems_install_cmd
 
 # Install required version of bundler.
-bundler_install_cmd = "sudo gem install bundler -v 0.9.2 --no-ri --no-rdoc"
+bundler_install_cmd = "sudo gem install bundler -v 0.9.3 --no-ri --no-rdoc"
 puts "Running command: #{bundler_install_cmd}"
 build_results[:install_bundler] = system bundler_install_cmd
 
@@ -33,7 +33,7 @@ cd root_dir do
   puts
   puts "[CruiseControl] Bundling RubyGems"
   puts
-  build_results[:bundle] = system 'sudo env CI=1 bundle install'
+  build_results[:bundle] = system 'env CI=1 bundle install'
 end
 
 cd "#{root_dir}/activesupport" do
diff --git a/rails.gemspec b/rails.gemspec
index 3c293a250f..fa79fee152 100644
--- a/rails.gemspec
+++ b/rails.gemspec
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
   s.add_dependency('activeresource',   '= 3.0.0.beta1')
   s.add_dependency('actionmailer',     '= 3.0.0.beta1')
   s.add_dependency('railties',         '= 3.0.0.beta1')
-  s.add_dependency('bundler',          '>= 0.9.2')
+  s.add_dependency('bundler',          '>= 0.9.3')
 end
-- 
cgit v1.2.3


From a4c32897585dde2b939b269f23ea537393e6fc0b Mon Sep 17 00:00:00 2001
From: Chad Woolley 
Date: Sat, 6 Feb 2010 22:33:45 -0700
Subject: remove all sudo references from CI build script

Signed-off-by: Jeremy Kemper 
---
 ci/ci_build.rb | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/ci/ci_build.rb b/ci/ci_build.rb
index a227902032..6dcff3149a 100755
--- a/ci/ci_build.rb
+++ b/ci/ci_build.rb
@@ -18,14 +18,8 @@ end
 puts "[CruiseControl] Rails build"
 build_results = {}
 
-# Install rubygems-update, so 'gem update --system' in cruise_config.rb auto-installs it on next build.
-# This is how you can auto-update rubygems without logging in to CI system
-rubygems_install_cmd = "sudo gem install rubygems-update -v 1.3.5 --no-ri --no-rdoc"
-puts "Running command: #{rubygems_install_cmd}"
-build_results[:install_rubygems_update] = system rubygems_install_cmd
-
 # Install required version of bundler.
-bundler_install_cmd = "sudo gem install bundler -v 0.9.3 --no-ri --no-rdoc"
+bundler_install_cmd = "gem install bundler -v 0.9.3 --no-ri --no-rdoc"
 puts "Running command: #{bundler_install_cmd}"
 build_results[:install_bundler] = system bundler_install_cmd
 
-- 
cgit v1.2.3


From bb55bbd207836d6d2eb1aa3dff1170f81a60131f Mon Sep 17 00:00:00 2001
From: Mikel Lindsaar 
Date: Sun, 7 Feb 2010 18:32:52 +1100
Subject: Fixing actionmailer tests for CI

---
 actionmailer/test/base_test.rb | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb
index 7e794e10e8..222db66aaa 100644
--- a/actionmailer/test/base_test.rb
+++ b/actionmailer/test/base_test.rb
@@ -461,7 +461,8 @@ class BaseTest < ActiveSupport::TestCase
     assert_instance_of Mail::Message, mail
   end
 
-  test "calling deliver on the action should increment the deliveries collection" do
+  test "calling deliver on the action should increment the deliveries collection if using the test mailer" do
+    BaseMailer.delivery_method = :test
     BaseMailer.deliveries.clear
     BaseMailer.welcome.deliver
     assert_equal(1, BaseMailer.deliveries.length)
-- 
cgit v1.2.3


From ca1879b7308d0d7e096ff1bf17cc4f70ce4d5b8c Mon Sep 17 00:00:00 2001
From: Dan Kubb 
Date: Sun, 7 Feb 2010 08:29:18 +0100
Subject: Added newline to appended gem config in Gemfile

Signed-off-by: Yehuda Katz 
---
 railties/lib/rails/generators/actions.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 247a141943..152fe6e33e 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -81,7 +81,7 @@ module Rails
         end
 
         in_root do
-          append_file "Gemfile", "gem #{parts.join(", ")}", :verbose => false
+          append_file "Gemfile", "gem #{parts.join(", ")}\n", :verbose => false
         end
       end
 
-- 
cgit v1.2.3


From de69c798db5535f19bfd585da83117fe1dacd6d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= 
Date: Sat, 6 Feb 2010 20:55:25 +0100
Subject: Fix nested attributes with specified collection.

---
 actionpack/lib/action_view/helpers/form_helper.rb | 18 +++++++++++-------
 actionpack/test/template/form_helper_test.rb      | 22 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 238f2eb07a..ce21af9923 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -1172,7 +1172,9 @@ module ActionView
 
         def fields_for_with_nested_attributes(association_name, args, block)
           name = "#{object_name}[#{association_name}_attributes]"
-          association = args.first.to_model if args.first.respond_to?(:to_model)
+          options = args.extract_options!
+          association = args.shift
+          association = association.to_model if association.respond_to?(:to_model)
 
           if association.respond_to?(:new_record?)
             association = [association] if @object.send(association_name).is_a?(Array)
@@ -1181,20 +1183,22 @@ module ActionView
           end
 
           if association.is_a?(Array)
-            explicit_child_index = args.last[:child_index] if args.last.is_a?(Hash)
+            explicit_child_index = options[:child_index]
             association.map do |child|
-              fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, args, block)
+              fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, options, block)
             end.join
           elsif association
-            fields_for_nested_model(name, association, args, block)
+            fields_for_nested_model(name, association, options, block)
           end
         end
 
-        def fields_for_nested_model(name, object, args, block)
+        def fields_for_nested_model(name, object, options, block)
+          object = object.to_model if object.respond_to?(:to_model)
+
           if object.new_record?
-            @template.fields_for(name, object, *args, &block)
+            @template.fields_for(name, object, options, &block)
           else
-            @template.fields_for(name, object, *args) do |builder|
+            @template.fields_for(name, object, options) do |builder|
               block.call(builder)
               @template.concat builder.hidden_field(:id) unless builder.emitted_hidden_id?
             end
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index f2d524bd1b..7b909fff82 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -918,6 +918,28 @@ class FormHelperTest < ActionView::TestCase
     assert_dom_equal expected, output_buffer
   end
 
+  def test_nested_fields_for_with_existing_records_on_a_supplied_nested_attributes_collection_different_from_record_one
+    comments = Array.new(2) { |id| Comment.new(id + 1) }
+    @post.comments = []
+
+    form_for(:post, @post) do |f|
+      concat f.text_field(:title)
+      f.fields_for(:comments, comments) do |cf|
+        concat cf.text_field(:name)
+      end
+    end
+
+    expected = '
' + + '' + + '' + + '' + + '' + + '' + + '
' + + assert_dom_equal expected, output_buffer + end + def test_nested_fields_for_on_a_nested_attributes_collection_association_yields_only_builder @post.comments = [Comment.new(321), Comment.new] yielded_comments = [] -- cgit v1.2.3 From 345e0b274cb384f8d453256e90dd105e6c2ffa19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 7 Feb 2010 13:44:47 +0100 Subject: Add backtrace cleaner on test unit railtie. --- activesupport/lib/active_support/test_case.rb | 6 ------ railties/lib/rails/test_unit/railtie.rb | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index 1646891e00..ab30984d62 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -21,12 +21,6 @@ module ActiveSupport alias_method :method_name, :name if method_defined? :name alias_method :method_name, :__name__ if method_defined? :__name__ else - # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit - if defined?(Rails) && ENV['BACKTRACE'].nil? - require 'rails/backtrace_cleaner' - Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } - end - Assertion = Test::Unit::AssertionFailedError require 'active_support/testing/default' diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb index 21b9dbc074..f7f07ac053 100644 --- a/railties/lib/rails/test_unit/railtie.rb +++ b/railties/lib/rails/test_unit/railtie.rb @@ -13,5 +13,13 @@ module Rails rake_tasks do load "rails/test_unit/testing.rake" end + + initializer "test_unit.backtrace_cleaner" do + # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit + unless defined?(Minitest) || ENV['BACKTRACE'] + require 'rails/backtrace_cleaner' + Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } + end + end end end \ No newline at end of file -- cgit v1.2.3 From d6ae930c9cfacf50d65b2880ac21efe80801a33d Mon Sep 17 00:00:00 2001 From: RomD Date: Sun, 7 Feb 2010 04:56:19 +0100 Subject: fix ambiguous example for new invocation method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/guides/source/3_0_release_notes.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/guides/source/3_0_release_notes.textile b/railties/guides/source/3_0_release_notes.textile index 1624172176..639e775bf5 100644 --- a/railties/guides/source/3_0_release_notes.textile +++ b/railties/guides/source/3_0_release_notes.textile @@ -39,8 +39,8 @@ h4. script/* replaced by script/rails The new script/rails replaces all the scripts that used to be in the script directory. You do not run script/rails directly though, the +rails+ command detects it is being invoked in the root of a Rails application and runs the script for you. Intended usage is: -rails console # => ./script/rails console -rails g scaffold post title:string # => ./script/rails generate scaffold post title:string +rails console # instead of script/console +rails g scaffold post title:string # instead of script/generate scaffold post title:string Run rails --help for a list of all the options. -- cgit v1.2.3 From 518b4ff478984b74085239b0aa69fe67f7c01d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 7 Feb 2010 14:36:50 +0100 Subject: Check if Test::Unit is defined before adding backtrace filter. --- .../generators/rails/app/templates/test/test_helper.rb | 1 + railties/lib/rails/test_unit/railtie.rb | 2 +- railties/test/application/test_test.rb | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/railties/lib/generators/rails/app/templates/test/test_helper.rb b/railties/lib/generators/rails/app/templates/test/test_helper.rb index 45b551fc7d..005149eba0 100644 --- a/railties/lib/generators/rails/app/templates/test/test_helper.rb +++ b/railties/lib/generators/rails/app/templates/test/test_helper.rb @@ -1,4 +1,5 @@ ENV["RAILS_ENV"] = "test" +require 'test/unit' require File.expand_path(File.dirname(__FILE__) + "/../config/environment") require 'rails/test_help' diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb index f7f07ac053..b0a4b460af 100644 --- a/railties/lib/rails/test_unit/railtie.rb +++ b/railties/lib/rails/test_unit/railtie.rb @@ -16,7 +16,7 @@ module Rails initializer "test_unit.backtrace_cleaner" do # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit - unless defined?(Minitest) || ENV['BACKTRACE'] + if defined?(Test::Unit::Util::BacktraceFilter) && ENV['BACKTRACE'].nil? require 'rails/backtrace_cleaner' Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } end diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index 37175783d8..de316a6fd0 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -23,6 +23,23 @@ module ApplicationTests run_test 'unit/foo_test.rb' end + # Run just in Ruby < 1.9 + if defined?(Test::Unit::Util::BacktraceFilter) + test "adds backtrace cleaner" do + app_file 'test/unit/backtrace_test.rb', <<-RUBY + require 'test_helper' + + class FooTest < ActiveSupport::TestCase + def test_truth + assert Test::Unit::Util::BacktraceFilter.ancestors.include?(Rails::BacktraceFilterForTestUnit) + end + end + RUBY + + run_test 'unit/backtrace_test.rb' + end + end + test "integration test" do controller 'posts', <<-RUBY class PostsController < ActionController::Base -- cgit v1.2.3 From a1a6e54d14b70e1d418d4939328e6eb24bdd8f3b Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 7 Feb 2010 11:41:49 -0800 Subject: Fix doc typo and update fast_xs URL. Thanks to Dmitrii Golub. --- activesupport/lib/active_support/core_ext/file/atomic.rb | 2 +- activesupport/lib/active_support/core_ext/string/xchar.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb index 249fb1362d..49d28e8a34 100644 --- a/activesupport/lib/active_support/core_ext/file/atomic.rb +++ b/activesupport/lib/active_support/core_ext/file/atomic.rb @@ -9,7 +9,7 @@ class File # If your temp directory is not on the same filesystem as the file you're # trying to write, you can provide a different temporary directory. # - # File.atomic_write("/data/something.important", "/data/tmp") do |f| + # File.atomic_write("/data/something.important", "/data/tmp") do |file| # file.write("hello") # end def self.atomic_write(file_name, temp_dir = Dir.tmpdir) diff --git a/activesupport/lib/active_support/core_ext/string/xchar.rb b/activesupport/lib/active_support/core_ext/string/xchar.rb index 7183218634..f9a5b4fb64 100644 --- a/activesupport/lib/active_support/core_ext/string/xchar.rb +++ b/activesupport/lib/active_support/core_ext/string/xchar.rb @@ -1,5 +1,5 @@ begin - # See http://bogomips.org/fast_xs/ by Eric Wong. + # See http://fast-xs.rubyforge.org/ by Eric Wong. # Also included with hpricot. require 'fast_xs' rescue LoadError -- cgit v1.2.3 From b235af702a086dd06fa9849ee47942e8ce82090d Mon Sep 17 00:00:00 2001 From: Gabriel Mansour Date: Sat, 30 Jan 2010 12:38:33 -0500 Subject: Fix pluralization for numbers formatted like '1.00' Signed-off-by: Jeremy Kemper --- actionpack/lib/action_view/helpers/text_helper.rb | 2 +- actionpack/test/template/text_helper_test.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 412e0c82cb..b63617322f 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -187,7 +187,7 @@ module ActionView # pluralize(0, 'person') # # => 0 people def pluralize(count, singular, plural = nil) - "#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize)) + "#{count || 0} " + ((count == 1 || count =~ /^1(\.0+)?$/) ? singular : (plural || singular.pluralize)) end # Wraps the +text+ into lines no longer than +line_width+ width. This method diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 088c07b8bb..39bea12501 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -228,6 +228,8 @@ class TextHelperTest < ActionView::TestCase assert_equal("2 counts", pluralize('2', "count")) assert_equal("1,066 counts", pluralize('1,066', "count")) assert_equal("1.25 counts", pluralize('1.25', "count")) + assert_equal("1.0 count", pluralize('1.0', "count")) + assert_equal("1.00 count", pluralize('1.00', "count")) assert_equal("2 counters", pluralize(2, "count", "counters")) assert_equal("0 counters", pluralize(nil, "count", "counters")) assert_equal("2 people", pluralize(2, "person")) -- cgit v1.2.3 From afd2e19be3b74effa3fdb9c4affd48f0aaede838 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sun, 7 Feb 2010 23:03:13 +0100 Subject: removes Module#included_in_classes, which is no longer used --- .../lib/active_support/core_ext/module.rb | 1 - .../active_support/core_ext/module/inclusion.rb | 30 ---------------------- activesupport/test/core_ext/module_test.rb | 7 ----- 3 files changed, 38 deletions(-) delete mode 100644 activesupport/lib/active_support/core_ext/module/inclusion.rb diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb index fbe89fe07c..b9c9614ca6 100644 --- a/activesupport/lib/active_support/core_ext/module.rb +++ b/activesupport/lib/active_support/core_ext/module.rb @@ -1,7 +1,6 @@ require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/module/introspection' -require 'active_support/core_ext/module/inclusion' require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/module/attr_internal' require 'active_support/core_ext/module/attr_accessor_with_default' diff --git a/activesupport/lib/active_support/core_ext/module/inclusion.rb b/activesupport/lib/active_support/core_ext/module/inclusion.rb deleted file mode 100644 index 4f23841645..0000000000 --- a/activesupport/lib/active_support/core_ext/module/inclusion.rb +++ /dev/null @@ -1,30 +0,0 @@ -class Module - # Returns the classes in the current ObjectSpace where this module has been - # mixed in according to Module#included_modules. - # - # module M - # end - # - # module N - # include M - # end - # - # class C - # include M - # end - # - # class D < C - # end - # - # p M.included_in_classes # => [C, D] - # - def included_in_classes - classes = [] - ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) } - - classes.reverse.inject([]) do |unique_classes, klass| - unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s) - unique_classes - end - end -end \ No newline at end of file diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index 87f056ea85..23016fd329 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -72,13 +72,6 @@ class ModuleTest < Test::Unit::TestCase @david = Someone.new("David", Somewhere.new("Paulina", "Chicago")) end - def test_included_in_classes - assert One.included_in_classes.include?(Ab) - assert One.included_in_classes.include?(Xy::Bc) - assert One.included_in_classes.include?(Yz::Zy::Cd) - assert !One.included_in_classes.include?(De) - end - def test_delegation_to_methods assert_equal "Paulina", @david.street assert_equal "Chicago", @david.city -- cgit v1.2.3 From cf9a52a7b6a4cb28709f116b306e06395b40b752 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sun, 7 Feb 2010 23:06:15 +0100 Subject: removes Module#as_load_path, which is no longer used --- .../lib/active_support/core_ext/module.rb | 1 - .../lib/active_support/core_ext/module/loading.rb | 25 ---------------------- activesupport/test/core_ext/module_test.rb | 5 ----- activesupport/test/dependencies_test.rb | 5 ----- 4 files changed, 36 deletions(-) delete mode 100644 activesupport/lib/active_support/core_ext/module/loading.rb diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb index b9c9614ca6..41600929f4 100644 --- a/activesupport/lib/active_support/core_ext/module.rb +++ b/activesupport/lib/active_support/core_ext/module.rb @@ -5,5 +5,4 @@ require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/module/attr_internal' require 'active_support/core_ext/module/attr_accessor_with_default' require 'active_support/core_ext/module/delegation' -require 'active_support/core_ext/module/loading' require 'active_support/core_ext/module/synchronization' diff --git a/activesupport/lib/active_support/core_ext/module/loading.rb b/activesupport/lib/active_support/core_ext/module/loading.rb deleted file mode 100644 index 43d0578ae6..0000000000 --- a/activesupport/lib/active_support/core_ext/module/loading.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'active_support/core_ext/string/inflections' - -class Module - # Returns String#underscore applied to the module name minus trailing classes. - # - # ActiveRecord.as_load_path # => "active_record" - # ActiveRecord::Associations.as_load_path # => "active_record/associations" - # ActiveRecord::Base.as_load_path # => "active_record" (Base is a class) - # - # The Kernel module gives an empty string by definition. - # - # Kernel.as_load_path # => "" - # Math.as_load_path # => "math" - def as_load_path - if self == Object || self == Kernel - '' - elsif is_a? Class - parent == self ? '' : parent.as_load_path - else - name.split('::').collect do |word| - word.underscore - end * '/' - end - end -end \ No newline at end of file diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index 23016fd329..1fe75d5930 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -163,11 +163,6 @@ class ModuleTest < Test::Unit::TestCase def test_local_constants assert_equal %w(Constant1 Constant3), Ab.local_constants.sort.map(&:to_s) end - - def test_as_load_path - assert_equal 'yz/zy', Yz::Zy.as_load_path - assert_equal 'yz', Yz.as_load_path - end end module BarMethodAliaser diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 0fcf1eaf00..f782313411 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -1,7 +1,6 @@ require 'abstract_unit' require 'pp' require 'active_support/dependencies' -require 'active_support/core_ext/module/loading' require 'active_support/core_ext/kernel/reporting' module ModuleWithMissing @@ -130,10 +129,6 @@ class DependenciesTest < Test::Unit::TestCase end end - def test_as_load_path - assert_equal '', DependenciesTest.as_load_path - end - def test_module_loading with_autoloading_fixtures do assert_kind_of Module, A -- cgit v1.2.3 From 5fe3dc4bf52eb315310a714c0fc1f627d47428fa Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Mon, 8 Feb 2010 15:30:10 +1100 Subject: Adding ruby version spec to all gemspec files to at least 1.8.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionmailer/actionmailer.gemspec | 1 + actionpack/actionpack.gemspec | 1 + activemodel/activemodel.gemspec | 1 + activerecord/activerecord.gemspec | 1 + activeresource/activeresource.gemspec | 1 + activesupport/activesupport.gemspec | 1 + rails.gemspec | 3 ++- rails3b.gemspec | 1 + railties/railties.gemspec | 1 + 9 files changed, 10 insertions(+), 1 deletion(-) diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index d5c0a4c9c4..31d8efc7bf 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = 'Email composition, delivery, and recieval framework (part of Rails).' s.description = 'Email composition, delivery, and recieval framework (part of Rails).' + s.required_ruby_version = '>= 1.8.7' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index ef141f2202..a35c4aac72 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = 'Web-flow and rendering framework putting the VC in MVC (part of Rails).' s.description = 'Web-flow and rendering framework putting the VC in MVC (part of Rails).' + s.required_ruby_version = '>= 1.8.7' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index e5b0207e39..b4fbe26d97 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = "A toolkit for building other modeling frameworks like ActiveRecord" s.description = %q{Extracts common modeling concerns from ActiveRecord to share between similar frameworks like ActiveResource.} + s.required_ruby_version = '>= 1.8.7' s.author = "David Heinemeier Hansson" s.email = "david@loudthinking.com" diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index 82a31b262b..aeaafbb694 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = 'Object-relational mapper framework (part of Rails).' s.description = 'Object-relational mapper framework (part of Rails).' + s.required_ruby_version = '>= 1.8.7' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/activeresource/activeresource.gemspec b/activeresource/activeresource.gemspec index 51a381ccc8..1722ebeb8e 100644 --- a/activeresource/activeresource.gemspec +++ b/activeresource/activeresource.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = 'REST-model framework (part of Rails).' s.description = 'REST-model framework (part of Rails).' + s.required_ruby_version = '>= 1.8.7' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index d169392dfc..d0557230aa 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = 'Support and utility classes used by the Rails framework.' s.description = 'Support and utility classes used by the Rails framework.' + s.required_ruby_version = '>= 1.8.7' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' diff --git a/rails.gemspec b/rails.gemspec index fa79fee152..1460dd5688 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -4,12 +4,13 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = 'Full-stack web-application framework.' s.description = 'Full-stack web-application framework.' + s.required_ruby_version = '>= 1.8.7' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' s.homepage = 'http://www.rubyonrails.org' s.rubyforge_project = 'rails' - + s.files = [] s.require_path = [] diff --git a/rails3b.gemspec b/rails3b.gemspec index 4aa342e6c0..e28f752e97 100644 --- a/rails3b.gemspec +++ b/rails3b.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0' s.summary = 'Just the Rails 3 beta dependencies. Works around prerelease RubyGems bug.' s.description = 'My kingdom for working dependencies.' + s.required_ruby_version = '>= 1.8.7' s.author = 'Jeremy Kemper' s.email = 'jeremy@bitsweat.net' diff --git a/railties/railties.gemspec b/railties/railties.gemspec index 4fedb64c93..65d2dde89f 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -4,6 +4,7 @@ Gem::Specification.new do |s| s.version = '3.0.0.beta1' s.summary = 'Controls boot-up, rake tasks and generators for the Rails framework.' s.description = 'Controls boot-up, rake tasks and generators for the Rails framework.' + s.required_ruby_version = '>= 1.8.7' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' -- cgit v1.2.3 From 17b451898c09f560cef105ea120d8e767256555a Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Mon, 8 Feb 2010 18:57:00 +1100 Subject: Updating Prototype to 1.6.1 and script.aculo.us to 1.8.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../app/templates/public/javascripts/controls.js | 8 +- .../app/templates/public/javascripts/dragdrop.js | 13 +- .../app/templates/public/javascripts/effects.js | 21 +- .../app/templates/public/javascripts/prototype.js | 2592 ++++++++++++-------- 4 files changed, 1593 insertions(+), 1041 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/controls.js b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js index ca29aefdd1..7392fb664c 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/controls.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js @@ -1,6 +1,8 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) +// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2009 Jon Tirsen (http://www.tirsen.com) // Contributors: // Richard Livsey // Rahul Bhargava diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js index 07229f986f..15c6dbca68 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js @@ -1,5 +1,6 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) +// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ @@ -311,7 +312,7 @@ var Draggable = Class.create({ tag_name=='TEXTAREA')) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); + var pos = this.element.cumulativeOffset(); this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); Draggables.activate(this); @@ -454,7 +455,7 @@ var Draggable = Class.create({ }, draw: function(point) { - var pos = Position.cumulativeOffset(this.element); + var pos = this.element.cumulativeOffset(); if(this.options.ghosting) { var r = Position.realOffset(this.element); pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; @@ -730,7 +731,7 @@ var Sortable = { } // keep reference - this.sortables[element.id] = options; + this.sortables[element.identify()] = options; // for onupdate Draggables.addObserver(new SortableObserver(element, options.onUpdate)); @@ -825,7 +826,7 @@ var Sortable = { hide().addClassName('dropmarker').setStyle({position:'absolute'}); document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); } - var offsets = Position.cumulativeOffset(dropon); + var offsets = dropon.cumulativeOffset(); Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); if(position=='after') diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/effects.js b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js index 5a639d2dea..066ee5909c 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/effects.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js @@ -1,4 +1,6 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) @@ -145,14 +147,13 @@ var Effect = { 'blind': ['BlindDown','BlindUp'], 'appear': ['Appear','Fade'] }, - toggle: function(element, effect) { + toggle: function(element, effect, options) { element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ + effect = (effect || 'appear').toLowerCase(); + + return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({ queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, arguments[2] || { }); - Effect[element.visible() ? - Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + }, options || {})); } }; @@ -228,12 +229,6 @@ Effect.Queue = Effect.Queues.get('global'); Effect.Base = Class.create({ position: null, start: function(options) { - function codeForEvent(options,eventName){ - return ( - (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + - (options[eventName] ? 'this.options.'+eventName+'(this);' : '') - ); - } if (options && options.transition === false) options.transition = Effect.Transitions.linear; this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); this.currentFrame = 0; diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js index dfe8ab4e13..9fe6e1243b 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js @@ -1,5 +1,5 @@ -/* Prototype JavaScript framework, version 1.6.0.3 - * (c) 2005-2008 Sam Stephenson +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://www.prototypejs.org/ @@ -7,26 +7,43 @@ *--------------------------------------------------------------------------*/ var Prototype = { - Version: '1.6.0.3', - - Browser: { - IE: !!(window.attachEvent && - navigator.userAgent.indexOf('Opera') === -1), - Opera: navigator.userAgent.indexOf('Opera') > -1, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && - navigator.userAgent.indexOf('KHTML') === -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }, + Version: '1.6.1', + + Browser: (function(){ + var ua = navigator.userAgent; + var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; + return { + IE: !!window.attachEvent && !isOpera, + Opera: isOpera, + WebKit: ua.indexOf('AppleWebKit/') > -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), BrowserFeatures: { XPath: !!document.evaluate, SelectorsAPI: !!document.querySelector, - ElementExtensions: !!window.HTMLElement, - SpecificElementExtensions: - document.createElement('div')['__proto__'] && - document.createElement('div')['__proto__'] !== - document.createElement('form')['__proto__'] + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() }, ScriptFragment: ']*>([\\S\\s]*?)<\/script>', @@ -40,9 +57,30 @@ if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false; +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + /* Based on Alex Arnell's inheritance implementation. */ -var Class = { - create: function() { + +var Class = (function() { + function subclass() {}; + function create() { var parent = null, properties = $A(arguments); if (Object.isFunction(properties[0])) parent = properties.shift(); @@ -56,7 +94,6 @@ var Class = { klass.subclasses = []; if (parent) { - var subclass = function() { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); @@ -69,18 +106,19 @@ var Class = { klass.prototype.initialize = Prototype.emptyFunction; klass.prototype.constructor = klass; - return klass; } -}; -Class.Methods = { - addMethods: function(source) { + function addMethods(source) { var ancestor = this.superclass && this.superclass.prototype; var properties = Object.keys(source); - if (!Object.keys({ toString: true }).length) - properties.push("toString", "valueOf"); + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } for (var i = 0, length = properties.length; i < length; i++) { var property = properties[i], value = source[property]; @@ -88,7 +126,7 @@ Class.Methods = { value.argumentNames().first() == "$super") { var method = value; value = (function(m) { - return function() { return ancestor[m].apply(this, arguments) }; + return function() { return ancestor[m].apply(this, arguments); }; })(property).wrap(method); value.valueOf = method.valueOf.bind(method); @@ -99,29 +137,36 @@ Class.Methods = { return this; } -}; -var Abstract = { }; + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { -Object.extend = function(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; -}; + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } -Object.extend(Object, { - inspect: function(object) { + function inspect(object) { try { - if (Object.isUndefined(object)) return 'undefined'; + if (isUndefined(object)) return 'undefined'; if (object === null) return 'null'; return object.inspect ? object.inspect() : String(object); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } - }, + } - toJSON: function(object) { + function toJSON(object) { var type = typeof object; switch (type) { case 'undefined': @@ -132,131 +177,180 @@ Object.extend(Object, { if (object === null) return 'null'; if (object.toJSON) return object.toJSON(); - if (Object.isElement(object)) return; + if (isElement(object)) return; var results = []; for (var property in object) { - var value = Object.toJSON(object[property]); - if (!Object.isUndefined(value)) + var value = toJSON(object[property]); + if (!isUndefined(value)) results.push(property.toJSON() + ': ' + value); } return '{' + results.join(', ') + '}'; - }, + } - toQueryString: function(object) { + function toQueryString(object) { return $H(object).toQueryString(); - }, + } - toHTML: function(object) { + function toHTML(object) { return object && object.toHTML ? object.toHTML() : String.interpret(object); - }, + } - keys: function(object) { - var keys = []; + function keys(object) { + var results = []; for (var property in object) - keys.push(property); - return keys; - }, + results.push(property); + return results; + } - values: function(object) { - var values = []; + function values(object) { + var results = []; for (var property in object) - values.push(object[property]); - return values; - }, + results.push(object[property]); + return results; + } - clone: function(object) { - return Object.extend({ }, object); - }, + function clone(object) { + return extend({ }, object); + } - isElement: function(object) { + function isElement(object) { return !!(object && object.nodeType == 1); - }, + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } - isArray: function(object) { - return object != null && typeof object == "object" && - 'splice' in object && 'join' in object; - }, - isHash: function(object) { + function isHash(object) { return object instanceof Hash; - }, + } - isFunction: function(object) { - return typeof object == "function"; - }, + function isFunction(object) { + return typeof object === "function"; + } - isString: function(object) { - return typeof object == "string"; - }, + function isString(object) { + return _toString.call(object) == "[object String]"; + } - isNumber: function(object) { - return typeof object == "number"; - }, + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } - isUndefined: function(object) { - return typeof object == "undefined"; + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); } -}); -Object.extend(Function.prototype, { - argumentNames: function() { - var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') .replace(/\s+/g, '').split(','); return names.length == 1 && !names[0] ? [] : names; - }, + } - bind: function() { + function bind(context) { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = $A(arguments), object = args.shift(); + var __method = this, args = slice.call(arguments, 1); return function() { - return __method.apply(object, args.concat($A(arguments))); + var a = merge(args, arguments); + return __method.apply(context, a); } - }, + } - bindAsEventListener: function() { - var __method = this, args = $A(arguments), object = args.shift(); + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); return function(event) { - return __method.apply(object, [event || window.event].concat(args)); + var a = update([event || window.event], args); + return __method.apply(context, a); } - }, + } - curry: function() { + function curry() { if (!arguments.length) return this; - var __method = this, args = $A(arguments); + var __method = this, args = slice.call(arguments, 0); return function() { - return __method.apply(this, args.concat($A(arguments))); + var a = merge(args, arguments); + return __method.apply(this, a); } - }, + } - delay: function() { - var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 return window.setTimeout(function() { return __method.apply(__method, args); }, timeout); - }, + } - defer: function() { - var args = [0.01].concat($A(arguments)); + function defer() { + var args = update([0.01], arguments); return this.delay.apply(this, args); - }, + } - wrap: function(wrapper) { + function wrap(wrapper) { var __method = this; return function() { - return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); } - }, + } - methodize: function() { + function methodize() { if (this._methodized) return this._methodized; var __method = this; return this._methodized = function() { - return __method.apply(null, [this].concat($A(arguments))); + var a = update([this], arguments); + return __method.apply(null, a); }; } -}); + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + Date.prototype.toJSON = function() { return '"' + this.getUTCFullYear() + '-' + @@ -267,30 +361,12 @@ Date.prototype.toJSON = function() { this.getUTCSeconds().toPaddedString(2) + 'Z"'; }; -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; RegExp.prototype.match = RegExp.prototype.test; RegExp.escape = function(str) { return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }; - -/*--------------------------------------------------------------------------*/ - var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.callback = callback; @@ -319,8 +395,10 @@ var PeriodicalExecuter = Class.create({ try { this.currentlyExecuting = true; this.execute(); - } finally { this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; } } } @@ -339,10 +417,25 @@ Object.extend(String, { } }); -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } while (source.length > 0) { if (match = source.match(pattern)) { @@ -354,69 +447,64 @@ Object.extend(String.prototype, { } } return result; - }, + } - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); count = Object.isUndefined(count) ? 1 : count; return this.gsub(pattern, function(match) { if (--count < 0) return match[0]; return replacement(match); }); - }, + } - scan: function(pattern, iterator) { + function scan(pattern, iterator) { this.gsub(pattern, iterator); return String(this); - }, + } - truncate: function(length, truncation) { + function truncate(length, truncation) { length = length || 30; truncation = Object.isUndefined(truncation) ? '...' : truncation; return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this); - }, + } - strip: function() { + function strip() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, + } - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } - stripScripts: function() { + function stripScripts() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, + } - extractScripts: function() { + function extractScripts() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); - }, + } - evalScripts: function() { + function evalScripts() { return this.extractScripts().map(function(script) { return eval(script) }); - }, + } - escapeHTML: function() { - var self = arguments.callee; - self.text.data = this; - return self.div.innerHTML; - }, + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } - unescapeHTML: function() { - var div = new Element('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? (div.childNodes.length > 1 ? - $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : - div.childNodes[0].nodeValue) : ''; - }, - toQueryParams: function(separator) { + function toQueryParams(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); if (!match) return { }; @@ -434,22 +522,22 @@ Object.extend(String.prototype, { } return hash; }); - }, + } - toArray: function() { + function toArray() { return this.split(''); - }, + } - succ: function() { + function succ() { return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - }, + } - times: function(count) { + function times(count) { return count < 1 ? '' : new Array(count + 1).join(this); - }, + } - camelize: function() { + function camelize() { var parts = this.split('-'), len = parts.length; if (len == 1) return parts[0]; @@ -461,101 +549,117 @@ Object.extend(String.prototype, { camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); return camelized; - }, + } - capitalize: function() { + function capitalize() { return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); - }, + } - underscore: function() { - return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); - }, + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } - dasherize: function() { - return this.gsub(/_/,'-'); - }, + function dasherize() { + return this.replace(/_/g, '-'); + } - inspect: function(useDoubleQuotes) { - var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { - var character = String.specialChar[match[0]]; - return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); }); if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - }, + } - toJSON: function() { + function toJSON() { return this.inspect(true); - }, + } - unfilterJSON: function(filter) { - return this.sub(filter || Prototype.JSONFilter, '#{1}'); - }, + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } - isJSON: function() { + function isJSON() { var str = this; if (str.blank()) return false; str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); - }, + } - evalJSON: function(sanitize) { + function evalJSON(sanitize) { var json = this.unfilterJSON(); try { if (!sanitize || json.isJSON()) return eval('(' + json + ')'); } catch (e) { } throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); - }, + } - include: function(pattern) { + function include(pattern) { return this.indexOf(pattern) > -1; - }, + } - startsWith: function(pattern) { + function startsWith(pattern) { return this.indexOf(pattern) === 0; - }, + } - endsWith: function(pattern) { + function endsWith(pattern) { var d = this.length - pattern.length; return d >= 0 && this.lastIndexOf(pattern) === d; - }, + } - empty: function() { + function empty() { return this == ''; - }, + } - blank: function() { + function blank() { return /^\s*$/.test(this); - }, - - interpolate: function(object, pattern) { - return new Template(this, pattern).evaluate(object); } -}); -if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { - escapeHTML: function() { - return this.replace(/&/g,'&').replace(//g,'>'); - }, - unescapeHTML: function() { - return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); } -}); -String.prototype.gsub.prepareReplacement = function(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -}; - -String.prototype.parseQuery = String.prototype.toQueryParams; - -Object.extend(String.prototype.escapeHTML, { - div: document.createElement('div'), - text: document.createTextNode('') -}); - -String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); var Template = Class.create({ initialize: function(template, pattern) { @@ -564,11 +668,11 @@ var Template = Class.create({ }, evaluate: function(object) { - if (Object.isFunction(object.toTemplateReplacements)) + if (object && Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { - if (object == null) return ''; + if (object == null) return (match[1] + ''); var before = match[1] || ''; if (before == '\\') return match[2]; @@ -579,7 +683,7 @@ var Template = Class.create({ if (match == null) return before; while (match != null) { - var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; ctx = ctx[comp]; if (null == ctx || '' == match[3]) break; expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); @@ -594,8 +698,8 @@ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; var $break = { }; -var Enumerable = { - each: function(iterator, context) { +var Enumerable = (function() { + function each(iterator, context) { var index = 0; try { this._each(function(value) { @@ -605,17 +709,17 @@ var Enumerable = { if (e != $break) throw e; } return this; - }, + } - eachSlice: function(number, iterator, context) { + function eachSlice(number, iterator, context) { var index = -number, slices = [], array = this.toArray(); if (number < 1) return array; while ((index += number) < array.length) slices.push(array.slice(index, index+number)); return slices.collect(iterator, context); - }, + } - all: function(iterator, context) { + function all(iterator, context) { iterator = iterator || Prototype.K; var result = true; this.each(function(value, index) { @@ -623,9 +727,9 @@ var Enumerable = { if (!result) throw $break; }); return result; - }, + } - any: function(iterator, context) { + function any(iterator, context) { iterator = iterator || Prototype.K; var result = false; this.each(function(value, index) { @@ -633,18 +737,18 @@ var Enumerable = { throw $break; }); return result; - }, + } - collect: function(iterator, context) { + function collect(iterator, context) { iterator = iterator || Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator.call(context, value, index)); }); return results; - }, + } - detect: function(iterator, context) { + function detect(iterator, context) { var result; this.each(function(value, index) { if (iterator.call(context, value, index)) { @@ -653,32 +757,32 @@ var Enumerable = { } }); return result; - }, + } - findAll: function(iterator, context) { + function findAll(iterator, context) { var results = []; this.each(function(value, index) { if (iterator.call(context, value, index)) results.push(value); }); return results; - }, + } - grep: function(filter, iterator, context) { + function grep(filter, iterator, context) { iterator = iterator || Prototype.K; var results = []; if (Object.isString(filter)) - filter = new RegExp(filter); + filter = new RegExp(RegExp.escape(filter)); this.each(function(value, index) { if (filter.match(value)) results.push(iterator.call(context, value, index)); }); return results; - }, + } - include: function(object) { + function include(object) { if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true; @@ -690,31 +794,31 @@ var Enumerable = { } }); return found; - }, + } - inGroupsOf: function(number, fillWith) { + function inGroupsOf(number, fillWith) { fillWith = Object.isUndefined(fillWith) ? null : fillWith; return this.eachSlice(number, function(slice) { while(slice.length < number) slice.push(fillWith); return slice; }); - }, + } - inject: function(memo, iterator, context) { + function inject(memo, iterator, context) { this.each(function(value, index) { memo = iterator.call(context, memo, value, index); }); return memo; - }, + } - invoke: function(method) { + function invoke(method) { var args = $A(arguments).slice(1); return this.map(function(value) { return value[method].apply(value, args); }); - }, + } - max: function(iterator, context) { + function max(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { @@ -723,9 +827,9 @@ var Enumerable = { result = value; }); return result; - }, + } - min: function(iterator, context) { + function min(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { @@ -734,9 +838,9 @@ var Enumerable = { result = value; }); return result; - }, + } - partition: function(iterator, context) { + function partition(iterator, context) { iterator = iterator || Prototype.K; var trues = [], falses = []; this.each(function(value, index) { @@ -744,26 +848,26 @@ var Enumerable = { trues : falses).push(value); }); return [trues, falses]; - }, + } - pluck: function(property) { + function pluck(property) { var results = []; this.each(function(value) { results.push(value[property]); }); return results; - }, + } - reject: function(iterator, context) { + function reject(iterator, context) { var results = []; this.each(function(value, index) { if (!iterator.call(context, value, index)) results.push(value); }); return results; - }, + } - sortBy: function(iterator, context) { + function sortBy(iterator, context) { return this.map(function(value, index) { return { value: value, @@ -773,13 +877,13 @@ var Enumerable = { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); - }, + } - toArray: function() { + function toArray() { return this.map(); - }, + } - zip: function() { + function zip() { var iterator = Prototype.K, args = $A(arguments); if (Object.isFunction(args.last())) iterator = args.pop(); @@ -788,130 +892,152 @@ var Enumerable = { return this.map(function(value, index) { return iterator(collections.pluck(index)); }); - }, + } - size: function() { + function size() { return this.toArray().length; - }, + } - inspect: function() { + function inspect() { return '#'; } -}; -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); function $A(iterable) { if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); + if ('toArray' in Object(iterable)) return iterable.toArray(); var length = iterable.length || 0, results = new Array(length); while (length--) results[length] = iterable[length]; return results; } -if (Prototype.Browser.WebKit) { - $A = function(iterable) { - if (!iterable) return []; - // In Safari, only use the `toArray` method if it's not a NodeList. - // A NodeList is a function, has an function `item` property, and a numeric - // `length` property. Adapted from Google Doctype. - if (!(typeof iterable === 'function' && typeof iterable.length === - 'number' && typeof iterable.item === 'function') && iterable.toArray) - return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - }; +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; } Array.from = $A; -Object.extend(Array.prototype, Enumerable); -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available -Object.extend(Array.prototype, { - _each: function(iterator) { + function each(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); - }, + } + if (!_each) _each = each; - clear: function() { + function clear() { this.length = 0; return this; - }, + } - first: function() { + function first() { return this[0]; - }, + } - last: function() { + function last() { return this[this.length - 1]; - }, + } - compact: function() { + function compact() { return this.select(function(value) { return value != null; }); - }, + } - flatten: function() { + function flatten() { return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; }); - }, + } - without: function() { - var values = $A(arguments); + function without() { + var values = slice.call(arguments, 0); return this.select(function(value) { return !values.include(value); }); - }, + } - reverse: function(inline) { + function reverse(inline) { return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { - return this.length > 1 ? this : this[0]; - }, + } - uniq: function(sorted) { + function uniq(sorted) { return this.inject([], function(array, value, index) { if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value); return array; }); - }, + } - intersect: function(array) { + function intersect(array) { return this.uniq().findAll(function(item) { return array.detect(function(value) { return item === value }); }); - }, + } - clone: function() { - return [].concat(this); - }, - size: function() { + function clone() { + return slice.call(this, 0); + } + + function size() { return this.length; - }, + } - inspect: function() { + function inspect() { return '[' + this.map(Object.inspect).join(', ') + ']'; - }, + } - toJSON: function() { + function toJSON() { var results = []; this.each(function(object) { var value = Object.toJSON(object); @@ -919,205 +1045,270 @@ Object.extend(Array.prototype, { }); return '[' + results.join(', ') + ']'; } -}); - -// use native browser JS 1.6 implementation if available -if (Object.isFunction(Array.prototype.forEach)) - Array.prototype._each = Array.prototype.forEach; - -if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; -}; - -if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; -}; -Array.prototype.toArray = Array.prototype.clone; + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { - var array = []; - for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + function concat() { + var array = slice.call(this, 0), item; for (var i = 0, length = arguments.length; i < length; i++) { - if (Object.isArray(arguments[i])) { - for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) - array.push(arguments[i][j]); + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); } else { - array.push(arguments[i]); + array.push(item); } } return array; - }; -} -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); - }, - - succ: function() { - return this + 1; - }, + } - times: function(iterator, context) { - $R(0, this, true).each(iterator, context); - return this; - }, + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - }, + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; - } -}); + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; -$w('abs round ceil floor').each(function(method){ - Number.prototype[method] = Math[method].methodize(); -}); + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); function $H(object) { return new Hash(object); }; var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } function toQueryPair(key, value) { if (Object.isUndefined(value)) return key; return key + '=' + encodeURIComponent(String.interpret(value)); } - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; - set: function(key, value) { - return this._object[key] = value; - }, + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } - get: function(key) { - // simulating poorly supported hasOwnProperty - if (this._object[key] !== Object.prototype[key]) - return this._object[key]; - }, + function inspect() { + return '#'; + } - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, + function toJSON() { + return Object.toJSON(this.toObject()); + } - toObject: function() { - return Object.clone(this._object); - }, + function clone() { + return new Hash(this); + } - keys: function() { - return this.pluck('key'); - }, + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); - values: function() { - return this.pluck('value'); - }, +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, + function succ() { + return this + 1; + } - merge: function(object) { - return this.clone().update(object); - }, + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } - toQueryString: function() { - return this.inject([], function(results, pair) { - var key = encodeURIComponent(pair.key), values = pair.value; + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return results.concat(values.map(toQueryPair.curry(key))); - } else results.push(toQueryPair(key, values)); - return results; - }).join('&'); - }, + function abs() { + return Math.abs(this); + } - inspect: function() { - return '#'; - }, + function round() { + return Math.round(this); + } - toJSON: function() { - return Object.toJSON(this.toObject()); - }, + function ceil() { + return Math.ceil(this); + } - clone: function() { - return new Hash(this); - } + function floor() { + return Math.floor(this); } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; })()); -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; -Hash.from = $H; -var ObjectRange = Class.create(Enumerable, { - initialize: function(start, end, exclusive) { +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; - }, + } - _each: function(iterator) { + function _each(iterator) { var value = this.start; while (this.include(value)) { iterator(value); value = value.succ(); } - }, + } - include: function(value) { + function include(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; } -}); -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -}; + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + var Ajax = { getTransport: function() { @@ -1164,7 +1355,6 @@ Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++ }, onComplete: function() { Ajax.activeRequestCount-- } }); - Ajax.Base = Class.create({ initialize: function(options) { this.options = { @@ -1186,7 +1376,6 @@ Ajax.Base = Class.create({ this.options.parameters = this.options.parameters.toObject(); } }); - Ajax.Request = Class.create(Ajax.Base, { _complete: false, @@ -1202,7 +1391,6 @@ Ajax.Request = Class.create(Ajax.Base, { var params = Object.clone(this.options.parameters); if (!['get', 'post'].include(this.method)) { - // simulate other verbs over post params['_method'] = this.method; this.method = 'post'; } @@ -1210,7 +1398,6 @@ Ajax.Request = Class.create(Ajax.Base, { this.parameters = params; if (params = Object.toQueryString(params)) { - // when GET, append parameters to URL if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params; else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) @@ -1269,7 +1456,6 @@ Ajax.Request = Class.create(Ajax.Base, { headers['Connection'] = 'close'; } - // user-defined headers if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; @@ -1323,7 +1509,6 @@ Ajax.Request = Class.create(Ajax.Base, { } if (state == 'Complete') { - // avoid memory leak in MSIE: clean up this.transport.onreadystatechange = Prototype.emptyFunction; } }, @@ -1340,7 +1525,7 @@ Ajax.Request = Class.create(Ajax.Base, { getHeader: function(name) { try { return this.transport.getResponseHeader(name) || null; - } catch (e) { return null } + } catch (e) { return null; } }, evalResponse: function() { @@ -1360,6 +1545,13 @@ Ajax.Request = Class.create(Ajax.Base, { Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + Ajax.Response = Class.create({ initialize: function(request){ this.request = request; @@ -1381,6 +1573,7 @@ Ajax.Response = Class.create({ }, status: 0, + statusText: '', getStatus: Ajax.Request.prototype.getStatus, @@ -1510,6 +1703,9 @@ Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); + + + function $(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) @@ -1537,7 +1733,6 @@ if (Prototype.BrowserFeatures.XPath) { if (!window.Node) var Node = { }; if (!Node.ELEMENT_NODE) { - // DOM level 2 ECMAScript Language Binding Object.extend(Node, { ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, @@ -1554,13 +1749,30 @@ if (!Node.ELEMENT_NODE) { }); } -(function() { - var element = this.Element; - this.Element = function(tagName, attributes) { + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { attributes = attributes || { }; tagName = tagName.toLowerCase(); var cache = Element.cache; - if (Prototype.Browser.IE && attributes.name) { + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { tagName = '<' + tagName + ' name="' + attributes.name + '">'; delete attributes.name; return Element.writeAttribute(document.createElement(tagName), attributes); @@ -1568,11 +1780,12 @@ if (!Node.ELEMENT_NODE) { if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); }; - Object.extend(this.Element, element || { }); - if (element) this.Element.prototype = element.prototype; -}).call(window); + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); Element.cache = { }; +Element.idCounter = 1; Element.Methods = { visible: function(element) { @@ -1585,6 +1798,7 @@ Element.Methods = { return element; }, + hide: function(element) { element = $(element); element.style.display = 'none'; @@ -1603,15 +1817,89 @@ Element.Methods = { return element; }, - update: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - content = Object.toHTML(content); - element.innerHTML = content.stripScripts(); - content.evalScripts.bind(content).defer(); - return element; - }, + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), replace: function(element, content) { element = $(element); @@ -1696,11 +1984,11 @@ Element.Methods = { }, ancestors: function(element) { - return $(element).recursivelyCollect('parentNode'); + return Element.recursivelyCollect(element, 'parentNode'); }, descendants: function(element) { - return $(element).select("*"); + return Element.select(element, "*"); }, firstDescendant: function(element) { @@ -1717,16 +2005,17 @@ Element.Methods = { }, previousSiblings: function(element) { - return $(element).recursivelyCollect('previousSibling'); + return Element.recursivelyCollect(element, 'previousSibling'); }, nextSiblings: function(element) { - return $(element).recursivelyCollect('nextSibling'); + return Element.recursivelyCollect(element, 'nextSibling'); }, siblings: function(element) { element = $(element); - return element.previousSiblings().reverse().concat(element.nextSiblings()); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); }, match: function(element, selector) { @@ -1738,22 +2027,22 @@ Element.Methods = { up: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(element.parentNode); - var ancestors = element.ancestors(); + var ancestors = Element.ancestors(element); return Object.isNumber(expression) ? ancestors[expression] : Selector.findElement(ancestors, expression, index); }, down: function(element, expression, index) { element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - return Object.isNumber(expression) ? element.descendants()[expression] : + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : Element.select(element, expression)[index || 0]; }, previous: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); + var previousSiblings = Element.previousSiblings(element); return Object.isNumber(expression) ? previousSiblings[expression] : Selector.findElement(previousSiblings, expression, index); }, @@ -1761,27 +2050,28 @@ Element.Methods = { next: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); + var nextSiblings = Element.nextSiblings(element); return Object.isNumber(expression) ? nextSiblings[expression] : Selector.findElement(nextSiblings, expression, index); }, - select: function() { - var args = $A(arguments), element = $(args.shift()); + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); return Selector.findChildElements(element, args); }, - adjacent: function() { - var args = $A(arguments), element = $(args.shift()); + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); return Selector.findChildElements(element.parentNode, args).without(element); }, identify: function(element) { element = $(element); - var id = element.readAttribute('id'), self = arguments.callee; + var id = Element.readAttribute(element, 'id'); if (id) return id; - do { id = 'anonymous_element_' + self.counter++ } while ($(id)); - element.writeAttribute('id', id); + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); return id; }, @@ -1820,11 +2110,11 @@ Element.Methods = { }, getHeight: function(element) { - return $(element).getDimensions().height; + return Element.getDimensions(element).height; }, getWidth: function(element) { - return $(element).getDimensions().width; + return Element.getDimensions(element).width; }, classNames: function(element) { @@ -1840,7 +2130,7 @@ Element.Methods = { addClassName: function(element, className) { if (!(element = $(element))) return; - if (!element.hasClassName(className)) + if (!Element.hasClassName(element, className)) element.className += (element.className ? ' ' : '') + className; return element; }, @@ -1854,11 +2144,10 @@ Element.Methods = { toggleClassName: function(element, className) { if (!(element = $(element))) return; - return element[element.hasClassName(className) ? - 'removeClassName' : 'addClassName'](className); + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); }, - // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); var node = element.firstChild; @@ -1892,7 +2181,7 @@ Element.Methods = { scrollTo: function(element) { element = $(element); - var pos = element.cumulativeOffset(); + var pos = Element.cumulativeOffset(element); window.scrollTo(pos[0], pos[1]); return element; }, @@ -1940,18 +2229,17 @@ Element.Methods = { getDimensions: function(element) { element = $(element); - var display = element.getStyle('display'); + var display = Element.getStyle(element, 'display'); if (display != 'none' && display != null) // Safari bug return {width: element.offsetWidth, height: element.offsetHeight}; - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; var originalDisplay = els.display; els.visibility = 'hidden'; - els.position = 'absolute'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + els.position = 'absolute'; els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; @@ -1967,8 +2255,6 @@ Element.Methods = { if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined if (Prototype.Browser.Opera) { element.style.top = 0; element.style.left = 0; @@ -2034,10 +2320,9 @@ Element.Methods = { absolutize: function(element) { element = $(element); - if (element.getStyle('position') == 'absolute') return element; - // Position.prepare(); // To be done manually by Scripty when it needs it. + if (Element.getStyle(element, 'position') == 'absolute') return element; - var offsets = element.positionedOffset(); + var offsets = Element.positionedOffset(element); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; @@ -2058,8 +2343,7 @@ Element.Methods = { relativize: function(element) { element = $(element); - if (element.getStyle('position') == 'relative') return element; - // Position.prepare(); // To be done manually by Scripty when it needs it. + if (Element.getStyle(element, 'position') == 'relative') return element; element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); @@ -2101,7 +2385,6 @@ Element.Methods = { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; - // Safari fix if (element.offsetParent == document.body && Element.getStyle(element, 'position') == 'absolute') break; @@ -2128,28 +2411,22 @@ Element.Methods = { offsetLeft: 0 }, arguments[2] || { }); - // find page position of source source = $(source); - var p = source.viewportOffset(); + var p = Element.viewportOffset(source); - // find coordinate system to use element = $(element); var delta = [0, 0]; var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas if (Element.getStyle(element, 'position') == 'absolute') { - parent = element.getOffsetParent(); - delta = parent.viewportOffset(); + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); } - // correct by body offsets (fixes Safari) if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop; } - // set position if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if (options.setWidth) element.style.width = source.offsetWidth + 'px'; @@ -2158,10 +2435,9 @@ Element.Methods = { } }; -Element.Methods.identify.counter = 1; - Object.extend(Element.Methods, { getElementsBySelector: Element.Methods.select, + childElements: Element.Methods.immediateDescendants }); @@ -2182,11 +2458,8 @@ if (Prototype.Browser.Opera) { case 'left': case 'top': case 'right': case 'bottom': if (proceed(element, 'position') === 'static') return null; case 'height': case 'width': - // returns '0px' for hidden elements; we want it to return null if (!Element.visible(element)) return null; - // returns the border-box dimensions rather than the content-box - // dimensions, so we subtract padding and borders from the value var dim = parseInt(proceed(element, style), 10); if (dim !== element['offset' + style.capitalize()]) @@ -2219,12 +2492,9 @@ if (Prototype.Browser.Opera) { } else if (Prototype.Browser.IE) { - // IE doesn't report offsets correctly for static elements, so we change them - // to "relative" to get the values, then change them back. Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( function(proceed, element) { element = $(element); - // IE throws an error if element is not in document try { element.offsetParent } catch(e) { return $(document.body) } var position = element.getStyle('position'); @@ -2244,8 +2514,6 @@ else if (Prototype.Browser.IE) { catch(e) { return Element._returnOffset(0,0) } var position = element.getStyle('position'); if (position !== 'static') return proceed(element); - // Trigger hasLayout on the offset parent so that IE6 reports - // accurate offsetTop and offsetLeft values for position: fixed. var offsetParent = element.getOffsetParent(); if (offsetParent && offsetParent.getStyle('position') === 'fixed') offsetParent.setStyle({ zoom: 1 }); @@ -2306,36 +2574,92 @@ else if (Prototype.Browser.IE) { return element; }; - Element._attributeTranslations = { - read: { - names: { - 'class': 'className', - 'for': 'htmlFor' - }, - values: { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - _getAttrNode: function(element, attribute) { - var node = element.getAttributeNode(attribute); - return node ? node.value : ""; - }, - _getEv: function(element, attribute) { - attribute = element.getAttribute(attribute); - return attribute ? attribute.toString().slice(23, -2) : null; - }, - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, - style: function(element) { - return element.style.cssText.toLowerCase(); + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp }, - title: function(element) { - return element.title; + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } } } } - }; + })(); Element._attributeTranslations.write = { names: Object.extend({ @@ -2363,8 +2687,8 @@ else if (Prototype.Browser.IE) { (function(v) { Object.extend(v, { - href: v._getAttr, - src: v._getAttr, + href: v._getAttr2, + src: v._getAttr2, type: v._getAttr, action: v._getAttrNode, disabled: v._flag, @@ -2391,6 +2715,26 @@ else if (Prototype.Browser.IE) { onchange: v._getEv }); })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + } else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { @@ -2420,9 +2764,6 @@ else if (Prototype.Browser.WebKit) { return element; }; - // Safari returns margins on body which is incorrect if the child is absolutely - // positioned. For performance reasons, redefine Element#cumulativeOffset for - // KHTML/WebKit only. Element.Methods.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { @@ -2438,30 +2779,7 @@ else if (Prototype.Browser.WebKit) { }; } -if (Prototype.Browser.IE || Prototype.Browser.Opera) { - // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements - Element.Methods.update = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - - content = Object.toHTML(content); - var tagName = element.tagName.toUpperCase(); - - if (tagName in Element._insertionTranslations.tags) { - $A(element.childNodes).each(function(node) { element.removeChild(node) }); - Element._getContentFromAnonymousElement(tagName, content.stripScripts()) - .each(function(node) { element.appendChild(node) }); - } - else element.innerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -if ('outerHTML' in document.createElement('div')) { +if ('outerHTML' in document.documentElement) { Element.Methods.replace = function(element, content) { element = $(element); @@ -2529,12 +2847,13 @@ Element._insertionTranslations = { }; (function() { - Object.extend(this.tags, { - THEAD: this.tags.TBODY, - TFOOT: this.tags.TBODY, - TH: this.tags.TD + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD }); -}).call(Element._insertionTranslations); +})(); Element.Methods.Simulated = { hasAttribute: function(element, attribute) { @@ -2548,41 +2867,81 @@ Element.Methods.ByTag = { }; Object.extend(Element, Element.Methods); -if (!Prototype.BrowserFeatures.ElementExtensions && - document.createElement('div')['__proto__']) { - window.HTMLElement = { }; - window.HTMLElement.prototype = document.createElement('div')['__proto__']; - Prototype.BrowserFeatures.ElementExtensions = true; -} +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) Element.extend = (function() { - if (Prototype.BrowserFeatures.SpecificElementExtensions) + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } return Prototype.K; + } var Methods = { }, ByTag = Element.Methods.ByTag; var extend = Object.extend(function(element) { - if (!element || element._extendedByPrototype || + if (!element || typeof element._extendedByPrototype != 'undefined' || element.nodeType != 1 || element == window) return element; var methods = Object.clone(Methods), - tagName = element.tagName.toUpperCase(), property, value; + tagName = element.tagName.toUpperCase(); - // extend methods for specific tags if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); - for (property in methods) { - value = methods[property]; - if (Object.isFunction(value) && !(property in element)) - element[property] = value.methodize(); - } + extendElementWith(element, methods); element._extendedByPrototype = Prototype.emptyFunction; return element; }, { refresh: function() { - // extend methods for all tags (Safari doesn't need this) if (!Prototype.BrowserFeatures.ElementExtensions) { Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated); @@ -2661,14 +3020,18 @@ Element.addMethods = function(methods) { klass = 'HTML' + tagName.capitalize() + 'Element'; if (window[klass]) return window[klass]; - window[klass] = { }; - window[klass].prototype = document.createElement(tagName)['__proto__']; - return window[klass]; + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; } + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + if (F.ElementExtensions) { - copy(Element.Methods, HTMLElement.prototype); - copy(Element.Methods.Simulated, HTMLElement.prototype, true); + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); } if (F.SpecificElementExtensions) { @@ -2686,38 +3049,109 @@ Element.addMethods = function(methods) { Element.cache = { }; }; -document.viewport = { - getDimensions: function() { - var dimensions = { }, B = Prototype.Browser; - $w('width height').each(function(d) { - var D = d.capitalize(); - if (B.WebKit && !document.evaluate) { - // Safari <3.0 needs self.innerWidth/Height - dimensions[d] = self['inner' + D]; - } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) { - // Opera <9.5 needs document.body.clientWidth/Height - dimensions[d] = document.body['client' + D] - } else { - dimensions[d] = document.documentElement['client' + D]; - } - }); - return dimensions; - }, - getWidth: function() { - return this.getDimensions().width; - }, +document.viewport = { - getHeight: function() { - return this.getDimensions().height; + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; }, getScrollOffsets: function() { return Element._returnOffset( window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); } }; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); /* Portions of the Selector class are derived from Jack Slocum's DomQuery, * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style * license. Please see http://www.yui-ext.com/ for more information. */ @@ -2738,31 +3172,52 @@ var Selector = Class.create({ }, - shouldUseXPath: function() { - if (!Prototype.BrowserFeatures.XPath) return false; + shouldUseXPath: (function() { - var e = this.expression; + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
'; - // Safari 3 chokes on :*-of-type and :empty - if (Prototype.Browser.WebKit && - (e.include("-of-type") || e.include(":empty"))) - return false; + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; - // XPath can't do namespaced attributes, nor can it read - // the "checked" property from DOM nodes - if ((/(\[[\w-]*?:|:checked)/).test(e)) - return false; + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - return true; - }, + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), shouldUseSelectorsAPI: function() { if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + if (!Selector._div) Selector._div = new Element('div'); - // Make sure the browser treats the selector as valid. Test on an - // isolated element to minimize cost of this check. try { Selector._div.querySelector(this.expression); } catch(e) { @@ -2774,7 +3229,7 @@ var Selector = Class.create({ compileMatcher: function() { var e = this.expression, ps = Selector.patterns, h = Selector.handlers, - c = Selector.criteria, le, p, m; + c = Selector.criteria, le, p, m, len = ps.length, name; if (Selector._cache[e]) { this.matcher = Selector._cache[e]; @@ -2786,11 +3241,12 @@ var Selector = Class.create({ while (e && le != e && (/\S/).test(e)) { le = e; - for (var i in ps) { - p = ps[i]; + for (var i = 0; i\s*/, - adjacent: /^\s*\+\s*/, - descendant: /^\s/, + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, - // selectors follow - tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, - id: /^#([\w\-\*]+)(\b|$)/, - className: /^\.([\w\-\*]+)(\b|$)/, - pseudo: -/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, - attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }, + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], - // for Selector.match and Element#match assertions: { tagName: function(element, matches) { return matches[1].toUpperCase() == element.tagName.toUpperCase(); @@ -3064,15 +3527,12 @@ Object.extend(Selector, { }, handlers: { - // UTILITY FUNCTIONS - // joins two collections concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) a.push(node); return a; }, - // marks an array of nodes for counting mark: function(nodes) { var _true = Prototype.emptyFunction; for (var i = 0, node; node = nodes[i]; i++) @@ -3080,15 +3540,32 @@ Object.extend(Selector, { return nodes; }, - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = undefined; - return nodes; - }, + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), - // mark each child node with its position (for nth calls) - // "ofType" flag indicates whether we're indexing for nth-of-type - // rather than nth-child index: function(parentNode, reverse, ofType) { parentNode._countedByPrototype = Prototype.emptyFunction; if (reverse) { @@ -3102,19 +3579,17 @@ Object.extend(Selector, { } }, - // filters out duplicates and extends all nodes unique: function(nodes) { if (nodes.length == 0) return nodes; var results = [], n; for (var i = 0, l = nodes.length; i < l; i++) - if (!(n = nodes[i])._countedByPrototype) { + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { n._countedByPrototype = Prototype.emptyFunction; results.push(Element.extend(n)); } return Selector.handlers.unmark(results); }, - // COMBINATOR FUNCTIONS descendant: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) @@ -3158,13 +3633,11 @@ Object.extend(Selector, { return null; }, - // TOKEN FUNCTIONS tagName: function(nodes, root, tagName, combinator) { var uTagName = tagName.toUpperCase(); var results = [], h = Selector.handlers; if (nodes) { if (combinator) { - // fastlane for ordinary descendant combinators if (combinator == "descendant") { for (var i = 0, node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName(tagName)); @@ -3180,8 +3653,19 @@ Object.extend(Selector, { id: function(nodes, root, id, combinator) { var targetNode = $(id), h = Selector.handlers; - if (!targetNode) return []; - if (!nodes && root == document) return [targetNode]; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + if (nodes) { if (combinator) { if (combinator == 'child') { @@ -3293,7 +3777,6 @@ Object.extend(Selector, { return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); }, - // handles the an+b logic getIndices: function(a, b, total) { if (a == 0) return b > 0 ? [b] : []; return $R(1, total).inject([], function(memo, i) { @@ -3302,7 +3785,6 @@ Object.extend(Selector, { }); }, - // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type nth: function(nodes, formula, root, reverse, ofType) { if (nodes.length == 0) return []; if (formula == 'even') formula = '2n+0'; @@ -3336,7 +3818,6 @@ Object.extend(Selector, { 'empty': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { - // IE treats comments as element nodes if (node.tagName == '!' || node.firstChild) continue; results.push(node); } @@ -3379,8 +3860,6 @@ Object.extend(Selector, { '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, - '$=': function(nv, v) { return nv.endsWith(v); }, - '*=': function(nv, v) { return nv.include(v); }, '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + '-').include('-' + (v || "").toUpperCase() + '-'); } @@ -3423,19 +3902,10 @@ Object.extend(Selector, { if (Prototype.Browser.IE) { Object.extend(Selector.handlers, { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) if (node.tagName !== "!") a.push(node); return a; - }, - - // IE improperly serializes _countedByPrototype in (inner|outer)HTML. - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node.removeAttribute('_countedByPrototype'); - return nodes; } }); } @@ -3443,9 +3913,11 @@ if (Prototype.Browser.IE) { function $$() { return Selector.findChildElements(document, $A(arguments)); } + var Form = { reset: function(form) { - $(form).reset(); + form = $(form); + form.reset(); return form; }, @@ -3460,7 +3932,6 @@ var Form = { if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) { if (key in result) { - // a key is already present; construct an array of values if (!Object.isArray(result[key])) result[key] = [result[key]]; result[key].push(value); } @@ -3480,13 +3951,18 @@ Form.Methods = { }, getElements: function(form) { - return $A($(form).getElementsByTagName('*')).inject([], - function(elements, child) { - if (Form.Element.Serializers[child.tagName.toLowerCase()]) - elements.push(Element.extend(child)); - return elements; - } - ); + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) }, getInputs: function(form, typeName, name) { @@ -3526,7 +4002,7 @@ Form.Methods = { }).sortBy(function(element) { return element.tabIndex }).first(); return firstByIndex ? firstByIndex : elements.find(function(element) { - return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + return /^(?:input|select|textarea)$/i.test(element.tagName); }); }, @@ -3557,6 +4033,7 @@ Form.Methods = { /*--------------------------------------------------------------------------*/ + Form.Element = { focus: function(element) { $(element).focus(); @@ -3570,6 +4047,7 @@ Form.Element = { }; Form.Element.Methods = { + serialize: function(element) { element = $(element); if (!element.disabled && element.name) { @@ -3610,7 +4088,7 @@ Form.Element.Methods = { try { element.focus(); if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) + !(/^(?:button|reset|submit)$/i.test(element.type)))) element.select(); } catch (e) { } return element; @@ -3632,6 +4110,7 @@ Form.Element.Methods = { /*--------------------------------------------------------------------------*/ var Field = Form.Element; + var $F = Form.Element.Methods.getValue; /*--------------------------------------------------------------------------*/ @@ -3694,13 +4173,13 @@ Form.Element.Serializers = { }, optionValue: function(opt) { - // extend element because hasAttribute may not be native return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; } }; /*--------------------------------------------------------------------------*/ + Abstract.TimedObserver = Class.create(PeriodicalExecuter, { initialize: function($super, element, frequency, callback) { $super(callback, frequency); @@ -3782,354 +4261,441 @@ Form.EventObserver = Class.create(Abstract.EventObserver, { return Form.serialize(this.element); } }); -if (!window.Event) var Event = { }; - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - KEY_HOME: 36, - KEY_END: 35, - KEY_PAGEUP: 33, - KEY_PAGEDOWN: 34, - KEY_INSERT: 45, - - cache: { }, - - relatedTarget: function(event) { - var element; - switch(event.type) { - case 'mouseover': element = event.fromElement; break; - case 'mouseout': element = event.toElement; break; - default: return null; - } - return Element.extend(element); - } -}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; -Event.Methods = (function() { - var isButton; + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + var _isButton; if (Prototype.Browser.IE) { var buttonMap = { 0: 1, 1: 4, 2: 2 }; - isButton = function(event, code) { - return event.button == buttonMap[code]; + _isButton = function(event, code) { + return event.button === buttonMap[code]; }; - } else if (Prototype.Browser.WebKit) { - isButton = function(event, code) { + _isButton = function(event, code) { switch (code) { case 0: return event.which == 1 && !event.metaKey; case 1: return event.which == 1 && event.metaKey; default: return false; } }; - } else { - isButton = function(event, code) { + _isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code); }; } - return { - isLeftClick: function(event) { return isButton(event, 0) }, - isMiddleClick: function(event) { return isButton(event, 1) }, - isRightClick: function(event) { return isButton(event, 2) }, - - element: function(event) { - event = Event.extend(event); - - var node = event.target, - type = event.type, - currentTarget = event.currentTarget; - - if (currentTarget && currentTarget.tagName) { - // Firefox screws up the "click" event when moving between radio buttons - // via arrow keys. It also screws up the "load" and "error" events on images, - // reporting the document as the target instead of the original image. - if (type === 'load' || type === 'error' || - (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' - && currentTarget.type === 'radio')) - node = currentTarget; - } - if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; - return Element.extend(node); - }, + function isLeftClick(event) { return _isButton(event, 0) } - findElement: function(event, expression) { - var element = Event.element(event); - if (!expression) return element; - var elements = [element].concat(element.ancestors()); - return Selector.findElement(elements, expression, 0); - }, + function isMiddleClick(event) { return _isButton(event, 1) } - pointer: function(event) { - var docElement = document.documentElement, - body = document.body || { scrollLeft: 0, scrollTop: 0 }; - return { - x: event.pageX || (event.clientX + - (docElement.scrollLeft || body.scrollLeft) - - (docElement.clientLeft || 0)), - y: event.pageY || (event.clientY + - (docElement.scrollTop || body.scrollTop) - - (docElement.clientTop || 0)) - }; - }, + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); - pointerX: function(event) { return Event.pointer(event).x }, - pointerY: function(event) { return Event.pointer(event).y }, + var node = event.target, type = event.type, + currentTarget = event.currentTarget; - stop: function(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - event.stopped = true; + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop }; -})(); -Event.extend = (function() { + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { m[name] = Event.Methods[name].methodize(); return m; }); if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + Object.extend(methods, { stopPropagation: function() { this.cancelBubble = true }, preventDefault: function() { this.returnValue = false }, - inspect: function() { return "[object Event]" } + inspect: function() { return '[object Event]' } }); - return function(event) { + Event.extend = function(event, element) { if (!event) return false; if (event._extendedByPrototype) return event; event._extendedByPrototype = Prototype.emptyFunction; var pointer = Event.pointer(event); + Object.extend(event, { - target: event.srcElement, - relatedTarget: Event.relatedTarget(event), + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), pageX: pointer.x, pageY: pointer.y }); + return Object.extend(event, methods); }; - } else { - Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__']; + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; Object.extend(Event.prototype, methods); - return Prototype.K; + Event.extend = Prototype.K; } -})(); -Object.extend(Event, (function() { - var cache = Event.cache; - - function getEventID(element) { - if (element._prototypeEventID) return element._prototypeEventID[0]; - arguments.callee.id = arguments.callee.id || 1; - return element._prototypeEventID = [++arguments.callee.id]; - } + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); - function getDOMEventName(eventName) { - if (eventName && eventName.include(':')) return "dataavailable"; - return eventName; - } + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } - function getCacheForID(id) { - return cache[id] = cache[id] || { }; - } + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } - function getWrappersForEventName(id, eventName) { - var c = getCacheForID(id); - return c[eventName] = c[eventName] || []; - } + if (respondersForEvent.pluck('handler').include(handler)) return false; - function createWrapper(element, eventName, handler) { - var id = getEventID(element); - var c = getWrappersForEventName(id, eventName); - if (c.pluck("handler").include(handler)) return false; + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; - var wrapper = function(event) { - if (!Event || !Event.extend || - (event.eventName && event.eventName != eventName)) + if (event.eventName !== eventName) return false; - Event.extend(event); - handler.call(element, event); - }; + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } - wrapper.handler = handler; - c.push(wrapper); - return wrapper; - } + if (parent === element) return; - function findWrapper(id, eventName, handler) { - var c = getWrappersForEventName(id, eventName); - return c.find(function(wrapper) { return wrapper.handler == handler }); - } + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } - function destroyWrapper(id, eventName, handler) { - var c = getCacheForID(id); - if (!c[eventName]) return false; - c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + responder.handler = handler; + respondersForEvent.push(responder); + return responder; } - function destroyCache() { - for (var id in cache) - for (var eventName in cache[id]) - cache[id][eventName] = null; + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } } + var CACHE = []; - // Internet Explorer needs to remove event handlers on page unload - // in order to avoid memory leaks. - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); - // Safari has a dummy event handler on page unload so that it won't - // use its bfcache. Safari <= 3.1 has an issue with restoring the "document" - // object when page is returned to via the back button using its bfcache. - if (Prototype.Browser.WebKit) { + if (Prototype.Browser.WebKit) window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; } - return { - observe: function(element, eventName, handler) { - element = $(element); - var name = getDOMEventName(eventName); + function observe(element, eventName, handler) { + element = $(element); - var wrapper = createWrapper(element, eventName, handler); - if (!wrapper) return element; + var responder = _createResponder(element, eventName, handler); - if (element.addEventListener) { - element.addEventListener(name, wrapper, false); - } else { - element.attachEvent("on" + name, wrapper); + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); } + } else { + var actualEventName = _getDOMEventName(eventName); - return element; - }, + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } - stopObserving: function(element, eventName, handler) { - element = $(element); - var id = getEventID(element), name = getDOMEventName(eventName); + return element; + } - if (!handler && eventName) { - getWrappersForEventName(id, eventName).each(function(wrapper) { - element.stopObserving(eventName, wrapper.handler); - }); - return element; + function stopObserving(element, eventName, handler) { + element = $(element); - } else if (!eventName) { - Object.keys(getCacheForID(id)).each(function(eventName) { - element.stopObserving(eventName); - }); - return element; - } + var registry = Element.retrieve(element, 'prototype_event_registry'); - var wrapper = findWrapper(id, eventName, handler); - if (!wrapper) return element; + if (Object.isUndefined(registry)) return element; - if (element.removeEventListener) { - element.removeEventListener(name, wrapper, false); - } else { - element.detachEvent("on" + name, wrapper); - } + if (eventName && !handler) { + var responders = registry.get(eventName); - destroyWrapper(id, eventName, handler); + if (Object.isUndefined(responders)) return element; + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); return element; - }, + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; - fire: function(element, eventName, memo) { - element = $(element); - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } - var event; - if (document.createEvent) { - event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - event = document.createEventObject(); - event.eventType = "ondataavailable"; - } + var responders = registry.get(eventName); - event.eventName = eventName; - event.memo = memo || { }; + if (!responders) return; - if (document.createEvent) { - element.dispatchEvent(event); - } else { - element.fireEvent(event.eventType, event); + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; - return Event.extend(event); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; } - }; -})()); -Object.extend(Event, Event.Methods); + event.eventName = eventName; + event.memo = memo || { }; -Element.addMethods({ - fire: Event.fire, - observe: Event.observe, - stopObserving: Event.stopObserving -}); + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); -Object.extend(document, { - fire: Element.Methods.fire.methodize(), - observe: Element.Methods.observe.methodize(), - stopObserving: Element.Methods.stopObserving.methodize(), - loaded: false -}); + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); (function() { /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ var timer; function fireContentLoadedEvent() { if (document.loaded) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); + if (timer) window.clearTimeout(timer); document.loaded = true; + document.fire('dom:loaded'); } - if (document.addEventListener) { - if (Prototype.Browser.WebKit) { - timer = window.setInterval(function() { - if (/loaded|complete/.test(document.readyState)) - fireContentLoadedEvent(); - }, 0); - - Event.observe(window, "load", fireContentLoadedEvent); + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } - } else { - document.addEventListener("DOMContentLoaded", - fireContentLoadedEvent, false); + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; } + fireContentLoadedEvent(); + } + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); } else { - document.write("