aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.rdoc2
-rw-r--r--actionmailer/lib/action_mailer/base.rb2
-rw-r--r--actionpack/CHANGELOG46
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb17
-rw-r--r--actionpack/lib/action_view/helpers/javascript_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb2
-rw-r--r--actionpack/lib/action_view/template.rb3
-rw-r--r--actionpack/test/abstract/layouts_test.rb12
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb3
-rw-r--r--actionpack/test/controller/caching_test.rb4
-rw-r--r--actionpack/test/controller/content_type_test.rb1
-rw-r--r--actionpack/test/template/erb_util_test.rb10
-rw-r--r--actionpack/test/template/javascript_helper_test.rb2
-rw-r--r--actionpack/test/template/number_helper_test.rb7
-rw-r--r--actionpack/test/template/template_test.rb5
-rw-r--r--activerecord/RUNNING_UNIT_TESTS16
-rw-r--r--activerecord/lib/active_record/base.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/railties/databases.rake2
-rw-r--r--activerecord/test/cases/adapters/mysql2/reserved_word_test.rb4
-rw-r--r--activerecord/test/cases/helper.rb11
-rw-r--r--activerecord/test/support/connection.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date/freeze.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb3
-rw-r--r--activesupport/test/core_ext/date_ext_test.rb6
-rw-r--r--railties/guides/source/active_record_validations_callbacks.textile10
-rw-r--r--railties/guides/source/asset_pipeline.textile4
-rw-r--r--railties/guides/source/command_line.textile96
-rw-r--r--railties/guides/source/configuring.textile26
-rw-r--r--railties/guides/source/contributing_to_ruby_on_rails.textile4
-rw-r--r--railties/guides/source/performance_testing.textile2
-rw-r--r--railties/lib/rails/application.rb12
-rw-r--r--railties/lib/rails/commands.rb6
-rw-r--r--railties/lib/rails/commands/generate.rb4
-rw-r--r--railties/lib/rails/commands/runner.rb4
-rw-r--r--railties/lib/rails/engine.rb12
-rw-r--r--railties/lib/rails/engine/commands.rb38
-rw-r--r--railties/lib/rails/generators.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb18
-rw-r--r--railties/lib/rails/generators/named_base.rb4
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt7
-rw-r--r--railties/lib/rails/railtie.rb5
-rw-r--r--railties/railties.gemspec1
-rw-r--r--railties/test/abstract_unit.rb1
-rw-r--r--railties/test/application/runner_test.rb4
-rw-r--r--railties/test/generators/namespaced_generators_test.rb10
-rw-r--r--railties/test/generators/plugin_new_generator_test.rb13
-rw-r--r--railties/test/generators/shared_generator_tests.rb4
-rw-r--r--railties/test/isolation/abstract_unit.rb2
-rw-r--r--railties/test/railties/engine_test.rb16
-rw-r--r--railties/test/railties/generators_test.rb115
-rw-r--r--railties/test/railties/shared_tests.rb19
55 files changed, 372 insertions, 252 deletions
diff --git a/README.rdoc b/README.rdoc
index 5abc6f927c..7e2d7850c8 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -1,7 +1,7 @@
== Welcome to Rails
Rails is a web-application framework that includes everything needed to create
-database-backed web applications according to the Model-View-Controller pattern.
+database-backed web applications according to the {Model-View-Controller (MVC)}[http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller] pattern.
Understanding the MVC pattern is key to understanding Rails. MVC divides your application
into three layers, each with a specific responsibility.
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index ccc25c775b..3b4e59d703 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -365,7 +365,7 @@ module ActionMailer #:nodoc:
Mail.register_observer(delivery_observer)
end
- # Register an Inteceptor which will be called before mail is sent.
+ # Register an Interceptor which will be called before mail is sent.
# Either a class or a string can be passed in as the Interceptor. If a string is passed in
# it will be <tt>constantize</tt>d.
def register_interceptor(interceptor)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 42baf6f45f..1965906df9 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,30 @@
*Rails 3.2.0 (unreleased)*
+* Refactor ActionController::TestCase cookies [Andrew White]
+
+ Assigning cookies for test cases should now use cookies[], e.g:
+
+ cookies[:email] = 'user@example.com'
+ get :index
+ assert_equal 'user@example.com', cookies[:email]
+
+ To clear the cookies, use clear, e.g:
+
+ cookies.clear
+ get :index
+ assert_nil cookies[:email]
+
+ We now no longer write out HTTP_COOKIE and the cookie jar is
+ persistent between requests so if you need to manipulate the environment
+ for your test you need to do it before the cookie jar is created.
+
+
+*Rails 3.1.0 (unreleased)*
+
+* json_escape will now return a SafeBuffer string if it receives SafeBuffer string [tenderlove]
+
+* Make sure escape_js returns SafeBuffer string if it receives SafeBuffer string [Prem Sichanugrist]
+
* Fix escape_js to work correctly with the new SafeBuffer restriction [Paul Gallagher]
* Brought back alternative convention for namespaced models in i18n [thoefer]
@@ -29,27 +54,6 @@
You can read more about this change in http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2e516e7acc96c4fb
-* Refactor ActionController::TestCase cookies [Andrew White]
-
- Assigning cookies for test cases should now use cookies[], e.g:
-
- cookies[:email] = 'user@example.com'
- get :index
- assert_equal 'user@example.com', cookies[:email]
-
- To clear the cookies, use clear, e.g:
-
- cookies.clear
- get :index
- assert_nil cookies[:email]
-
- We now no longer write out HTTP_COOKIE and the cookie jar is
- persistent between requests so if you need to manipulate the environment
- for your test you need to do it before the cookie jar is created.
-
-
-*Rails 3.1.0 (unreleased)*
-
* Added 'ActionView::Helpers::FormHelper.fields_for_with_index', similar to fields_for but allows to have access to the current iteration index [Jorge Bejar]
* Warn if we cannot verify CSRF token authenticity [José Valim]
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index ec76d1da1e..70ea419e81 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -49,6 +49,9 @@ module ActionDispatch
class Mapping #:nodoc:
IGNORE_OPTIONS = [:to, :as, :via, :on, :constraints, :defaults, :only, :except, :anchor, :shallow, :shallow_path, :shallow_prefix]
+ ANCHOR_CHARACTERS_REGEX = %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
+ SHORTHAND_REGEX = %r{^/[\w/]+$}
+ WILDCARD_PATH = %r{\*([^/]+)$}
def initialize(set, scope, path, options)
@set, @scope = set, scope
@@ -77,18 +80,18 @@ module ActionDispatch
# segment_keys.include?(k.to_s) || k == :controller
next unless Regexp === requirement && !constraints[name]
- if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
+ if requirement.source =~ ANCHOR_CHARACTERS_REGEX
raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
end
if requirement.multiline?
raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
end
end
- end
+ end
# match "account/overview"
def using_match_shorthand?(path, options)
- path && options.except(:via, :anchor, :to, :as).empty? && path =~ %r{^/[\w\/]+$}
+ path && options.except(:via, :anchor, :to, :as).empty? && path =~ SHORTHAND_REGEX
end
def normalize_path(path)
@@ -107,7 +110,7 @@ module ActionDispatch
# Add a constraint for wildcard route to make it non-greedy and match the
# optional format part of the route by default
- if path.match(/\*([^\/]+)$/) && @options[:format] != false
+ if path.match(WILDCARD_PATH) && @options[:format] != false
@options.reverse_merge!(:"#{$1}" => /.+?/)
end
@@ -1102,9 +1105,9 @@ module ActionDispatch
#
# The +comments+ resource here will have the following routes generated for it:
#
- # post_comments GET /sekret/posts/:post_id/comments(.:format)
- # post_comments POST /sekret/posts/:post_id/comments(.:format)
- # new_post_comment GET /sekret/posts/:post_id/comments/new(.:format)
+ # post_comments GET /posts/:post_id/comments(.:format)
+ # post_comments POST /posts/:post_id/comments(.:format)
+ # new_post_comment GET /posts/:post_id/comments/new(.:format)
# edit_comment GET /sekret/comments/:id/edit(.:format)
# comment GET /sekret/comments/:id(.:format)
# comment PUT /sekret/comments/:id(.:format)
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index 8a6f2e84be..4484390fde 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -18,7 +18,8 @@ module ActionView
# $('some_element').replaceWith('<%=j render 'some/element_template' %>');
def escape_javascript(javascript)
if javascript
- javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) {|match| JS_ESCAPE_MAP[match] }
+ result = javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) {|match| JS_ESCAPE_MAP[match] }
+ javascript.html_safe? ? result.html_safe : result
else
''
end
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 4dafb7739a..fe0288521f 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -211,7 +211,7 @@ module ActionView
defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
options = options.reverse_merge(defaults)
- parts = number.to_s.split('.')
+ parts = number.to_s.to_str.split('.')
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
parts.join(options[:separator]).html_safe
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 10797c010f..9c59d18310 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -218,6 +218,9 @@ module ActionView
method_name = self.method_name
if source.encoding_aware?
+ # Avoid performing in-place mutation for SafeBuffer
+ @source = source.to_str if source.html_safe?
+
# Look for # encoding: *. If we find one, we'll encode the
# String in that encoding, otherwise, we'll use the
# default external encoding.
diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb
index 5ed6aa68b5..86208899f8 100644
--- a/actionpack/test/abstract/layouts_test.rb
+++ b/actionpack/test/abstract/layouts_test.rb
@@ -87,18 +87,6 @@ module AbstractControllerTests
end
end
- class WithSymbolReturningString < Base
- layout :no_hello
-
- def index
- render :template => ActionView::Template::Text.new("Hello missing symbol!")
- end
- private
- def no_hello
- nil
- end
- end
-
class WithSymbolReturningNil < Base
layout :nilz
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index 7f3d943bba..a714e8bbcc 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -100,9 +100,6 @@ class AssertResponseWithUnexpectedErrorController < ActionController::Base
end
end
-class UserController < ActionController::Base
-end
-
module Admin
class InnerModuleController < ActionController::Base
def index
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 82c2c23607..da3314fe6d 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -127,7 +127,7 @@ class PageCachingTest < ActionController::TestCase
assert_equal 'I am xml', @response.body
end
- def test_should_cache_with_trailing_slash_on_url
+ def test_cached_page_should_not_have_trailing_slash_even_if_url_has_trailing_slash
@controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash/'
assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
end
@@ -141,7 +141,7 @@ class PageCachingTest < ActionController::TestCase
[:ok, :no_content, :found, :not_found].each do |status|
[:get, :post, :put, :delete].each do |method|
- unless method == :get and status == :ok
+ unless method == :get && status == :ok
define_method "test_shouldnt_cache_#{method}_with_#{status}_status" do
send(method, status)
assert_response status
diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb
index b12c798302..d51882066d 100644
--- a/actionpack/test/controller/content_type_test.rb
+++ b/actionpack/test/controller/content_type_test.rb
@@ -74,6 +74,7 @@ class ContentTypeTest < ActionController::TestCase
get :render_defaults
assert_equal "utf-16", @response.charset
assert_equal Mime::HTML, @response.content_type
+ ensure
OldContentTypeController.default_charset = "utf-8"
end
diff --git a/actionpack/test/template/erb_util_test.rb b/actionpack/test/template/erb_util_test.rb
index 30f6d1a213..790ab1c74c 100644
--- a/actionpack/test/template/erb_util_test.rb
+++ b/actionpack/test/template/erb_util_test.rb
@@ -16,6 +16,16 @@ class ErbUtilTest < Test::Unit::TestCase
end
end
+ def test_json_escape_returns_unsafe_strings_when_passed_unsafe_strings
+ value = json_escape("asdf")
+ assert !value.html_safe?
+ end
+
+ def test_json_escape_returns_safe_strings_when_passed_safe_strings
+ value = json_escape("asdf".html_safe)
+ assert value.html_safe?
+ end
+
def test_html_escape_is_html_safe
escaped = h("<p>")
assert_equal "&lt;p&gt;", escaped
diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb
index 15bd6b4c47..dd8b7b7cd5 100644
--- a/actionpack/test/template/javascript_helper_test.rb
+++ b/actionpack/test/template/javascript_helper_test.rb
@@ -35,6 +35,8 @@ class JavaScriptHelperTest < ActionView::TestCase
expect = %(\\'quoted\\' \\"double-quoted\\" new-line:\\n <\\/closed>)
assert_equal expect, escape_javascript(given)
assert_equal expect, escape_javascript(ActiveSupport::SafeBuffer.new(given))
+ assert_instance_of String, escape_javascript(given)
+ assert_instance_of ActiveSupport::SafeBuffer, escape_javascript(ActiveSupport::SafeBuffer.new(given))
end
def test_button_to_function
diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index 0104c20bc7..0e3475d98b 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -283,33 +283,40 @@ class NumberHelperTest < ActionView::TestCase
assert number_to_human(1).html_safe?
assert !number_to_human("<script></script>").html_safe?
assert number_to_human("asdf".html_safe).html_safe?
+ assert number_to_human("1".html_safe).html_safe?
assert number_to_human_size(1).html_safe?
assert number_to_human_size(1000000).html_safe?
assert !number_to_human_size("<script></script>").html_safe?
assert number_to_human_size("asdf".html_safe).html_safe?
+ assert number_to_human_size("1".html_safe).html_safe?
assert number_with_precision(1, :strip_insignificant_zeros => false).html_safe?
assert number_with_precision(1, :strip_insignificant_zeros => true).html_safe?
assert !number_with_precision("<script></script>").html_safe?
assert number_with_precision("asdf".html_safe).html_safe?
+ assert number_with_precision("1".html_safe).html_safe?
assert number_to_currency(1).html_safe?
assert !number_to_currency("<script></script>").html_safe?
assert number_to_currency("asdf".html_safe).html_safe?
+ assert number_to_currency("1".html_safe).html_safe?
assert number_to_percentage(1).html_safe?
assert !number_to_percentage("<script></script>").html_safe?
assert number_to_percentage("asdf".html_safe).html_safe?
+ assert number_to_percentage("1".html_safe).html_safe?
assert number_to_phone(1).html_safe?
assert_equal "&lt;script&gt;&lt;/script&gt;", number_to_phone("<script></script>")
assert number_to_phone("<script></script>").html_safe?
assert number_to_phone("asdf".html_safe).html_safe?
+ assert number_to_phone("1".html_safe).html_safe?
assert number_with_delimiter(1).html_safe?
assert !number_with_delimiter("<script></script>").html_safe?
assert number_with_delimiter("asdf".html_safe).html_safe?
+ assert number_with_delimiter("1".html_safe).html_safe?
end
def test_number_helpers_should_raise_error_if_invalid_when_specified
diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb
index b0ca7de0b6..2beb168a9d 100644
--- a/actionpack/test/template/template_test.rb
+++ b/actionpack/test/template/template_test.rb
@@ -172,5 +172,10 @@ class TestERBTemplate < ActiveSupport::TestCase
ensure
silence_warnings { Encoding.default_external = old }
end
+
+ def test_render_inline_safebuffer_should_not_raise_error
+ @template = new_template("Hello".html_safe)
+ render
+ end
end
end
diff --git a/activerecord/RUNNING_UNIT_TESTS b/activerecord/RUNNING_UNIT_TESTS
index 16444249cc..8fe9a357b4 100644
--- a/activerecord/RUNNING_UNIT_TESTS
+++ b/activerecord/RUNNING_UNIT_TESTS
@@ -9,24 +9,26 @@ You can build postgres and mysql databases using the build_postgresql and build_
You can run a particular test file from the command line, e.g.
- $ ruby test/cases/base_test.rb
+ $ ruby -Itest test/cases/base_test.rb
To run a specific test:
- $ ruby test/cases/base_test.rb -n test_something_works
+ $ ruby -Itest test/cases/base_test.rb -n test_something_works
You can run with a database other than the default you set in test/config.yml, using the ARCONN
environment variable:
- $ ARCONN=postgresql ruby test/cases/base_test.rb
+ $ ARCONN=postgresql ruby -Itest test/cases/base_test.rb
You can run all the tests for a given database via rake:
-To setup the testing environment for PostgreSQL use this command:
+ $ rake test_mysql
- rake postgresql:build_databases
+The 'rake test' task will run all the tests for mysql, mysql2, sqlite3 and postgresql.
-The incantation for running a particular test looks like this
+== Identity Map
- rake test TEST=test/cases/datatype_test_postgresql.rb TESTOPTS="--name=test_timestamp_with_zone_values_without_rails_time_zone_support"
+By default the tests run with the Identity Map turned off. But all tests should pass whether or
+not the identity map is on or off. You can turn it on using the IM env variable:
+ $ IM=true ruby -Itest test/case/base_test.rb
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index c2b09ad393..2f283ff6bc 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -659,8 +659,8 @@ module ActiveRecord #:nodoc:
def set_table_name(value = nil, &block)
@quoted_table_name = nil
define_attr_method :table_name, value, &block
+ @arel_table = nil
- @arel_table = Arel::Table.new(table_name, arel_engine)
@relation = Relation.new(self, arel_table)
end
alias :table_name= :set_table_name
@@ -892,7 +892,7 @@ module ActiveRecord #:nodoc:
end
def arel_table
- Arel::Table.new(table_name, arel_engine)
+ @arel_table ||= Arel::Table.new(table_name, arel_engine)
end
def arel_engine
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 8d7dd8bacf..9e6cb13cca 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -707,7 +707,7 @@ module ActiveRecord
def quoted_columns_for_index(column_names, options = {})
length = options[:length] if options.is_a?(Hash)
- quoted_column_names = case length
+ case length
when Hash
column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
when Fixnum
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 6f8f84d50b..6ef24a4eaf 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -498,7 +498,7 @@ namespace :railties do
# desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2"
task :migrations => :'db:load_config' do
to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
- railties = {}
+ railties = ActiveSupport::OrderedHash.new
Rails.application.railties.all do |railtie|
next unless to_load == :all || to_load.include?(railtie.railtie_name)
diff --git a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb
index 752b864818..3a9744e78f 100644
--- a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb
@@ -87,8 +87,8 @@ class MysqlReservedWordTest < ActiveRecord::TestCase
assert_nothing_raised { x.save }
x.order = 'y'
assert_nothing_raised { x.save }
- assert_nothing_raised { y = Group.find_by_order('y') }
- assert_nothing_raised { y = Group.find(1) }
+ assert_nothing_raised { Group.find_by_order('y') }
+ assert_nothing_raised { Group.find(1) }
x = Group.find(1)
end
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 110f6b97c6..d0dc9cb03d 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -12,19 +12,20 @@ require 'active_support/dependencies'
require 'support/config'
require 'support/connection'
-ARTest.connect
-
# TODO: Move all these random hacks into the ARTest namespace and into the support/ dir
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
-# Quote "type" if it's a reserved word for the current connection.
-QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
-
# Enable Identity Map only when ENV['IM'] is set to "true"
ActiveRecord::IdentityMap.enabled = (ENV['IM'] == "true")
+# Connect to the database
+ARTest.connect
+
+# Quote "type" if it's a reserved word for the current connection.
+QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
+
def current_adapter?(*types)
types.any? do |type|
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
diff --git a/activerecord/test/support/connection.rb b/activerecord/test/support/connection.rb
index fcd2e4dee5..a39794fa39 100644
--- a/activerecord/test/support/connection.rb
+++ b/activerecord/test/support/connection.rb
@@ -11,7 +11,7 @@ module ARTest
end
def self.connect
- puts "Using #{connection_name}"
+ puts "Using #{connection_name} with Identity Map #{ActiveRecord::IdentityMap.enabled? ? 'on' : 'off'}"
ActiveRecord::Base.logger = Logger.new("debug.log")
ActiveRecord::Base.configurations = connection_config
ActiveRecord::Base.establish_connection 'arunit'
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
index 7fabae3138..f420270dc4 100644
--- a/activesupport/lib/active_support/core_ext/array/wrap.rb
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -14,7 +14,7 @@ class Array
# This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
#
# * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
- # moves on to try +to_a+ if the returned value is +nil+, but <tt>Arraw.wrap</tt> returns
+ # moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
# such a +nil+ right away.
# * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
# raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
diff --git a/activesupport/lib/active_support/core_ext/date/freeze.rb b/activesupport/lib/active_support/core_ext/date/freeze.rb
index 4edd715ba2..a731f8345e 100644
--- a/activesupport/lib/active_support/core_ext/date/freeze.rb
+++ b/activesupport/lib/active_support/core_ext/date/freeze.rb
@@ -5,7 +5,7 @@
# first call will result in a frozen object error since the memo
# instance variable is uninitialized.
#
-# Work around by eagerly memoizing before freezing.
+# Work around by eagerly memoizing before the first freeze.
#
# Ruby 1.9 uses a preinitialized instance variable so it's unaffected.
# This hack is as close as we can get to feature detection:
@@ -17,9 +17,11 @@ if RUBY_VERSION < '1.9'
if frozen_object_error.message =~ /frozen/
class Date #:nodoc:
def freeze
- self.class.private_instance_methods(false).each do |m|
- if m.to_s =~ /\A__\d+__\Z/
- instance_variable_set(:"@#{m}", [send(m)])
+ unless frozen?
+ self.class.private_instance_methods(false).each do |m|
+ if m.to_s =~ /\A__\d+__\Z/
+ instance_variable_set(:"@#{m}", [send(m)])
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index 3a7652f5bf..1777a4b32d 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -113,7 +113,7 @@ class Module
raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
end
- prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_" || ''
+ prefix = options[:prefix] ? "#{options[:prefix] == true ? to : options[:prefix]}_" : ''
file, line = caller.first.split(':', 2)
line = line.to_i
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 aeb21ed8df..20e40fe40f 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -51,7 +51,8 @@ class ERB
# <%=j @person.to_json %>
#
def json_escape(s)
- s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
+ result = s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
+ s.html_safe? ? result.html_safe : result
end
alias j json_escape
diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb
index d81693209f..b4f848cd44 100644
--- a/activesupport/test/core_ext/date_ext_test.rb
+++ b/activesupport/test/core_ext/date_ext_test.rb
@@ -454,4 +454,10 @@ class DateExtBehaviorTest < Test::Unit::TestCase
Date.today.freeze.inspect
end
end
+
+ def test_can_freeze_twice
+ assert_nothing_raised do
+ Date.today.freeze.freeze
+ end
+ end
end
diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile
index 36094dcddc..50ff1c9ff7 100644
--- a/railties/guides/source/active_record_validations_callbacks.textile
+++ b/railties/guides/source/active_record_validations_callbacks.textile
@@ -182,7 +182,7 @@ It can receive an +:accept+ option, which determines the value that will be cons
<ruby>
class Person < ActiveRecord::Base
- validates :terms_of_service, :acceptance => true, :accept => 'yes'
+ validates :terms_of_service, :acceptance => { :accept => 'yes' }
end
</ruby>
@@ -338,7 +338,7 @@ WARNING. Note that the regular expression above allows a trailing newline charac
<ruby>
class Player < ActiveRecord::Base
validates :points, :numericality => true
- validates :games_played, :numericality => true, :only_integer => true
+ validates :games_played, :numericality => { :only_integer => true }
end
</ruby>
@@ -393,8 +393,8 @@ There is a +:scope+ option that you can use to specify other attributes that are
<ruby>
class Holiday < ActiveRecord::Base
- validates :name, :uniqueness => true, :scope => :year,
- :message => "should happen once per year"
+ validates :name, :uniqueness => { :scope => :year,
+ :message => "should happen once per year" }
end
</ruby>
@@ -402,7 +402,7 @@ There is also a +:case_sensitive+ option that you can use to define whether the
<ruby>
class Person < ActiveRecord::Base
- validates :name, :uniqueness => true, :case_sensitive => false
+ validates :name, :uniqueness => { :case_sensitive => false }
end
</ruby>
diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile
index 5d0dfee41c..c12bc3d1dc 100644
--- a/railties/guides/source/asset_pipeline.textile
+++ b/railties/guides/source/asset_pipeline.textile
@@ -32,9 +32,9 @@ Sprockets, the rails tie that powers the asset pipeline, provides three directiv
The require directive loads a file with the supplied basename from the following paths: app/assets/*, lib/assets/*, vendor/assets/*, as well as any of your gem's asset files.
-Require tree does...
+Using the +require_tree+ directive you can easily include an entire folder of assets. The paths must be relative, so begin them with either a forward slash or dots. For example to include a folder in the same directory you would do +require_tree ./folder_name+
-Require self does...
+Require self does... something
h4. Stacking Preprocessors
diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile
index 5fe9ad101b..026c15feba 100644
--- a/railties/guides/source/command_line.textile
+++ b/railties/guides/source/command_line.textile
@@ -5,7 +5,7 @@ Rails comes with every command line tool you'll need to
* Create a Rails application
* Generate models, controllers, database migrations, and unit tests
* Start a development server
-* Mess with objects through an interactive shell
+* Experiment with objects through an interactive shell
* Profile and benchmark your new creation
endprologue.
@@ -504,97 +504,3 @@ $ rails server mongrel
=> Rails 3.1.0 application starting on http://0.0.0.0:3000
...
</shell>
-
-h4. The Rails Generation: Generators
-
-INFO: For a good rundown on generators, see "Understanding Generators":http://wiki.rubyonrails.org/rails/pages/UnderstandingGenerators. A lot of its material is presented here.
-
-Generators are code that generates code. Let's experiment by building one. Our generator will generate a text file.
-
-The Rails generator by default looks in these places for available generators, where Rails.root is the root of your Rails application, like /home/foobar/commandsapp:
-
-* Rails.root/lib/generators
-* Rails.root/vendor/generators
-* Inside any plugin with a directory like "generators" or "rails_generators"
-* ~/.rails/generators
-* Inside any Gem you have installed with a name ending in "_generator"
-* Inside any Gem installed with a "rails_generators" path, and a file ending in "_generator.rb"
-* Finally, the builtin Rails generators (controller, model, mailer, etc.)
-
-Let's try the fourth option (in our home directory), which will be easy to clean up later:
-
-<shell>
-$ mkdir -p ~/.rails/generators/tutorial_test/templates
-$ touch ~/.rails/generators/tutorial_test/templates/tutorial.erb
-$ touch ~/.rails/generators/tutorial_test/tutorial_test_generator.rb
-</shell>
-
-We'll fill +tutorial_test_generator.rb+ out with:
-
-<ruby>
-class TutorialTestGenerator < Rails::Generator::Base
- def initialize(*runtime_args)
- super(*runtime_args)
- @tut_args = runtime_args
- end
-
- def manifest
- record do |m|
- m.directory "public"
- m.template "tutorial.erb", File.join("public", "tutorial.txt"),
- :assigns => { :args => @tut_args }
- end
- end
-end
-</ruby>
-
-We take whatever args are supplied, save them to an instance variable, and literally copying from the Rails source, implement a +manifest+ method, which calls +record+ with a block, and we:
-
-* Check there's a *public* directory. You bet there is.
-* Run the ERB template called "tutorial.erb".
-* Save it into "Rails.root/public/tutorial.txt".
-* Pass in the arguments we saved through the +:assigns+ parameter.
-
-Next we'll build the template:
-
-<shell>
-$ cat ~/.rails/generators/tutorial_test/templates/tutorial.erb
-I'm a template!
-
-I got assigned some args:
-<%= require 'pp'; PP.pp(args, "") %>
-</shell>
-
-Then we'll make sure it got included in the list of available generators:
-
-<shell>
-$ rails generate
-...
-...
-Installed Generators
- User: tutorial_test
-</shell>
-
-SWEET! Now let's generate some text, yeah!
-
-<shell>
-$ rails generate tutorial_test arg1 arg2 arg3
- exists public
- create public/tutorial.txt
-</shell>
-
-And the result:
-
-<shell>
-$ cat public/tutorial.txt
-I'm a template!
-
-I got assigned some args:
-[["arg1", "arg2", "arg3"],
- {:collision=>:ask,
- :quiet=>false,
- :generator=>"tutorial_test",
- :command=>:create}]
-</shell>
-
-Tada!
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index da951a0833..a4cc62c117 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -220,21 +220,21 @@ h4. Configuring Active Record
* +config.active_record.table_name_suffix+ lets you set a global string to be appended to table names. If you set this to +_northwest+, then the Customer class will look for +customers_northwest+ as its table. The default is an empty string.
-* +config.active_record.pluralize_table_names+ specifies whether Rails will look for singular or plural table names in the database. If set to +true+ (the default), then the Customer class will use the +customers+ table. If set to +false+, then the Customer class will use the +customer+ table.
+* +config.active_record.pluralize_table_names+ specifies whether Rails will look for singular or plural table names in the database. If set to true (the default), then the Customer class will use the +customers+ table. If set to false, then the Customer class will use the +customer+ table.
* +config.active_record.default_timezone+ determines whether to use +Time.local+ (if set to +:local+) or +Time.utc+ (if set to +:utc+) when pulling dates and times from the database. The default is +:utc+ for Rails, although Active Record defaults to +:local+ when used outside of Rails.
* +config.active_record.schema_format+ controls the format for dumping the database schema to a file. The options are +:ruby+ (the default) for a database-independent version that depends on migrations, or +:sql+ for a set of (potentially database-dependent) SQL statements.
-* +config.active_record.timestamped_migrations+ controls whether migrations are numbered with serial integers or with timestamps. The default is +true+, to use timestamps, which are preferred if there are multiple developers working on the same application.
+* +config.active_record.timestamped_migrations+ controls whether migrations are numbered with serial integers or with timestamps. The default is true, to use timestamps, which are preferred if there are multiple developers working on the same application.
-* +config.active_record.lock_optimistically+ controls whether Active Record will use optimistic locking. By default this is +true+.
+* +config.active_record.lock_optimistically+ controls whether Active Record will use optimistic locking and is true by default.
* +config.active_record.whitelist_attributes+ will create an empty whitelist of attributes available for mass-assignment security for all models in your app.
The MySQL adapter adds one additional configuration option:
-* +ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans+ controls whether Active Record will consider all +tinyint(1)+ columns in a MySQL database to be booleans. By default this is +true+.
+* +ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans+ controls whether Active Record will consider all +tinyint(1)+ columns in a MySQL database to be booleans and is true by default.
The schema dumper adds one additional configuration option:
@@ -260,7 +260,7 @@ h4. Configuring Action Controller
* +config.action_controller.request_forgery_protection_token+ sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ sets it to +:authenticity_token+ by default.
-* +config.action_controller.allow_forgery_protection+ enables or disables CSRF protection. By default this is +false+ in test mode and +true+ in all other modes.
+* +config.action_controller.allow_forgery_protection+ enables or disables CSRF protection. By default this is false in test mode and true in all other modes.
* +config.action_controller.relative_url_root+ can be used to tell Rails that you are deploying to a subdirectory. The default is +ENV['RAILS_RELATIVE_URL_ROOT']+.
@@ -350,11 +350,11 @@ There are a number of settings available on +config.action_mailer+:
** +:location+ - The location of the sendmail executable. Defaults to +/usr/sbin/sendmail+.
** +:arguments+ - The command line arguments. Defaults to +-i -t+.
-* +config.action_mailer.raise_delivery_errors+ specifies whether to raise an error if email delivery cannot be completed. It defaults to +true+.
+* +config.action_mailer.raise_delivery_errors+ specifies whether to raise an error if email delivery cannot be completed. It defaults to true.
* +config.action_mailer.delivery_method+ defines the delivery method. The allowed values are +:smtp+ (default), +:sendmail+, and +:test+.
-* +config.action_mailer.perform_deliveries+ specifies whether mail will actually be delivered. By default this is +true+; it can be convenient to set it to +false+ for testing.
+* +config.action_mailer.perform_deliveries+ specifies whether mail will actually be delivered and is true by default. It can be convenient to set it to false for testing.
* +config.action_mailer.default+ configures Action Mailer defaults. These default to:
<ruby>
@@ -366,12 +366,12 @@ There are a number of settings available on +config.action_mailer+:
* +config.action_mailer.observers+ registers observers which will be notified when mail is delivered.
<ruby>
-config.active_record.observers = ["MailObserver"]
+config.action_mailer.observers = ["MailObserver"]
</ruby>
* +config.action_mailer.interceptors+ registers interceptors which will be called before mail is sent.
<ruby>
-config.active_record.interceptors = ["MailInterceptor"]
+config.action_mailer.interceptors = ["MailInterceptor"]
</ruby>
h4. Configuring Active Resource
@@ -478,13 +478,13 @@ Serves as a placeholder so that +:load_environment_config+ can be defined to run
*+set_clear_dependencies_hook+* Provides a hook for +active_record.set_dispatch_hooks+ to use, which will run before this initializer. This initializer -- which runs only if +cache_classes+ is set to +false+ -- uses +ActionDispatch::Callbacks.after+ to remove the constants which have been referenced during the request from the object space so that they will be reloaded during the following request.
-*+initialize_dependency_mechanism+* If +config.cache_classes+ is set to +true+, configures +ActiveSupport::Dependencies.mechanism+ to +require+ dependencies rather than +load+ them.
+*+initialize_dependency_mechanism+* If +config.cache_classes+ is true, configures +ActiveSupport::Dependencies.mechanism+ to +require+ dependencies rather than +load+ them.
*+bootstrap_hook+* Runs all configured +before_initialize+ blocks.
*+i18n.callbacks+* In the development environment, sets up a +to_prepare+ callback which will call +I18n.reload!+ if any of the locales have changed since the last request. In production mode this callback will only run on the first request.
-*+active_support.initialize_whiny_nils+* Requires +active_support/whiny_nil+ if +config.whiny_nils+ is set to +true+. This file will output errors such as:
+*+active_support.initialize_whiny_nils+* Requires +active_support/whiny_nil+ if +config.whiny_nils+ is true. This file will output errors such as:
<plain>
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
@@ -568,13 +568,13 @@ The error occurred while evaluating nil.each
*+build_middleware_stack+* Builds the middleware stack for the application, returning an object which has a +call+ method which takes a Rack environment object for the request.
-*+eager_load!+* If +config.cache_classes+ is +true+, runs the +config.before_eager_load+ hooks and then calls +eager_load!+ which will load all the Ruby files from +config.eager_load_paths+.
+*+eager_load!+* If +config.cache_classes+ is true, runs the +config.before_eager_load+ hooks and then calls +eager_load!+ which will load all the Ruby files from +config.eager_load_paths+.
*+finisher_hook+* Provides a hook for after the initialization of process of the application is complete, as well as running all the +config.after_initialize+ blocks for the application, railties and engines.
*+set_routes_reloader+* Configures Action Dispatch to reload the routes file using +ActionDispatch::Callbacks.to_prepare+.
-*+disable_dependency_loading+* Disables the automatic dependency loading if the +config.cache_classes+ is set to +true+ and +config.dependency_loading+ is set to +false+.
+*+disable_dependency_loading+* Disables the automatic dependency loading if the +config.cache_classes+ is set to true and +config.dependency_loading+ is set to false.
h3. Changelog
diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile
index 2ce8ddc702..e6ec061c9a 100644
--- a/railties/guides/source/contributing_to_ruby_on_rails.textile
+++ b/railties/guides/source/contributing_to_ruby_on_rails.textile
@@ -350,7 +350,7 @@ Navigate to the Rails "GitHub repository":https://github.com/rails/rails and pre
Add the new remote to your local repository on your local machine:
<shell>
-$ git remote add mine https://<your user name>@github.com/<your user name>/rails.git
+$ git remote add mine git@github.com:<your user name>/rails.git
</shell>
Push to your remote:
@@ -361,7 +361,7 @@ $ git push mine my_new_branch
h4. Issue a Pull Request
-Navigate to the Rails repository you just pushed to (e.g. https://github.com/<your user name>/rails) and press "Pull Request" in the upper right hand corner.
+Navigate to the Rails repository you just pushed to (e.g. https://github.com/your-user-name/rails) and press "Pull Request" in the upper right hand corner.
Write your branch name in branch field (is filled with master by default) and press "Update Commit Range"
diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile
index 83db7eee59..fe0915bfea 100644
--- a/railties/guides/source/performance_testing.textile
+++ b/railties/guides/source/performance_testing.textile
@@ -573,7 +573,7 @@ h3. Useful Links
h4. Rails Plugins and Gems
* "Rails Analyzer":http://rails-analyzer.rubyforge.org
-* "Palmist":http://www.flyingmachinestudios.com/projects/
+* "Palmist":http://www.flyingmachinestudios.com/programming/announcing-palmist
* "Rails Footnotes":https://github.com/josevalim/rails-footnotes/tree/master
* "Query Reviewer":https://github.com/dsboulder/query_reviewer/tree/master
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 5a42ac0411..a2b2af98a6 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -105,14 +105,6 @@ module Rails
self
end
- def load_generators(app=self)
- initialize_generators
- railties.all { |r| r.load_generators(app) }
- Rails::Generators.configure!(app.config.generators)
- super
- self
- end
-
def load_console(app=self)
initialize_console
railties.all { |r| r.load_console(app) }
@@ -199,10 +191,6 @@ module Rails
end
end
- def initialize_generators
- require "rails/generators"
- end
-
def initialize_console
require "pp"
require "rails/console/app"
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index f22b4ef1f1..5e55aeada9 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -23,11 +23,7 @@ when 'generate', 'destroy', 'plugin'
require APP_PATH
Rails.application.require_environment!
- if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
- Rails.application.load_generators(engine)
- else
- Rails.application.load_generators
- end
+ Rails.application.load_generators
require "rails/commands/#{command}"
end
diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb
index b6f9a003d1..1fb2d98834 100644
--- a/railties/lib/rails/commands/generate.rb
+++ b/railties/lib/rails/commands/generate.rb
@@ -7,4 +7,6 @@ if ARGV.first.in?([nil, "-h", "--help"])
end
name = ARGV.shift
-Rails::Generators.invoke name, ARGV, :behavior => :invoke, :destination_root => Rails.root
+
+root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
+Rails::Generators.invoke name, ARGV, :behavior => :invoke, :destination_root => root
diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb
index f8b00e7249..e8cc5d9e3b 100644
--- a/railties/lib/rails/commands/runner.rb
+++ b/railties/lib/rails/commands/runner.rb
@@ -4,6 +4,10 @@ require 'rbconfig'
options = { :environment => (ENV['RAILS_ENV'] || "development").dup }
code_or_file = nil
+if ARGV.first.nil?
+ ARGV.push "-h"
+end
+
ARGV.clone.options do |opts|
script_name = File.basename($0)
opts.banner = "Usage: runner [options] ('Some.ruby(code)' or a filename)"
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 383be1802f..b358de89d0 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -330,6 +330,14 @@ module Rails
autoload :Configuration, "rails/engine/configuration"
autoload :Railties, "rails/engine/railties"
+ def load_generators(app=self)
+ initialize_generators
+ railties.all { |r| r.load_generators(app) }
+ Rails::Generators.configure!(app.config.generators)
+ super
+ self
+ end
+
class << self
attr_accessor :called_from, :isolated
alias :isolated? :isolated
@@ -567,6 +575,10 @@ module Rails
protected
+ def initialize_generators
+ require "rails/generators"
+ end
+
def routes?
defined?(@routes)
end
diff --git a/railties/lib/rails/engine/commands.rb b/railties/lib/rails/engine/commands.rb
new file mode 100644
index 0000000000..3b0920e213
--- /dev/null
+++ b/railties/lib/rails/engine/commands.rb
@@ -0,0 +1,38 @@
+require 'active_support/core_ext/object/inclusion'
+
+ARGV << '--help' if ARGV.empty?
+
+aliases = {
+ "g" => "generate"
+}
+
+command = ARGV.shift
+command = aliases[command] || command
+
+require ENGINE_PATH
+engine = ::Rails::Engine.find(ENGINE_ROOT)
+
+case command
+when 'generate', 'destroy'
+ require 'rails/generators'
+ Rails::Generators.namespace = engine.railtie_namespace
+ engine.load_generators
+ require "rails/commands/#{command}"
+
+when '--version', '-v'
+ ARGV.unshift '--version'
+ require 'rails/commands/application'
+
+else
+ puts "Error: Command not recognized" unless command.in?(['-h', '--help'])
+ puts <<-EOT
+Usage: rails COMMAND [ARGS]
+
+The common rails commands available for engines are:
+ generate Generate new code (short-cut alias: "g")
+ destroy Undo code generated with "generate"
+
+All commands can be run with -h for more information.
+ EOT
+ exit(1)
+end
diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb
index 09e505a75b..355b05ce0b 100644
--- a/railties/lib/rails/generators.rb
+++ b/railties/lib/rails/generators.rb
@@ -20,6 +20,8 @@ module Rails
autoload :ResourceHelpers, 'rails/generators/resource_helpers'
autoload :TestCase, 'rails/generators/test_case'
+ mattr_accessor :namespace
+
DEFAULT_ALIASES = {
:rails => {
:actions => '-a',
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 7972c72c1e..1196e2b7eb 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -188,13 +188,19 @@ module Rails
end
def bundle_command(command)
- require 'bundler'
- require 'bundler/cli'
-
say_status :run, "bundle #{command}"
- Bundler::CLI.new.send(command)
- rescue
- say_status :failure, "bundler raised an exception, are you offline?", :red
+
+ # We are going to shell out rather than invoking Bundler::CLI.new(command)
+ # because `rails new` loads the Thor gem and on the other hand bundler uses
+ # its own vendored Thor, which could be a different version. Running both
+ # things in the same process is a recipe for a night with paracetamol.
+ #
+ # We use backticks and #print here instead of vanilla #system because it
+ # is easier to silence stdout in the existing test suite this way. The
+ # end-user gets the bundler commands called anyway, so no big deal.
+ #
+ # Thanks to James Tucker for the Gem tricks involved in this call.
+ print `"#{Gem.ruby}" -rubygems "#{Gem.bin_path('bundler', 'bundle')}" #{command}`
end
def run_bundle
diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb
index 7e7f8d2d08..c6c0392f43 100644
--- a/railties/lib/rails/generators/named_base.rb
+++ b/railties/lib/rails/generators/named_base.rb
@@ -63,9 +63,7 @@ module Rails
end
def namespace
- @namespace ||= if defined?(Rails) && Rails.application
- Rails.application.class.parents.detect { |n| n.respond_to?(:_railtie) }
- end
+ Rails::Generators.namespace
end
def namespaced?
diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
index 11867a4cd7..807350316c 100644
--- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
+++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
@@ -126,6 +126,8 @@ task :default => :test
end
def script(force = false)
+ return unless full?
+
directory "script", :force => force do |content|
"#{shebang}\n" + content
end
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt
index 65d82abf6d..aa87d1b50c 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt
@@ -1,4 +1,7 @@
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
-ENGINE_PATH = File.expand_path('../..', __FILE__)
-load File.expand_path('../../<%= dummy_path %>/script/rails', __FILE__)
+ENGINE_ROOT = File.expand_path('../..', __FILE__)
+ENGINE_PATH = File.expand_path('../../lib/<%= name -%>/engine', __FILE__)
+
+require 'rails/all'
+require 'rails/engine/commands'
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index 65c567d72f..5f50943626 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -1,6 +1,7 @@
require 'rails/initializable'
require 'rails/configuration'
require 'active_support/inflector'
+require 'active_support/core_ext/module/introspection'
module Rails
# Railtie is the core of the Rails framework and provides several hooks to extend
@@ -192,5 +193,9 @@ module Rails
def load_generators(app)
self.class.generators.each { |block| block.call(app) }
end
+
+ def railtie_namespace
+ @railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:_railtie) }
+ end
end
end
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index f1c92bd5d4..9c535f4f90 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
s.add_dependency('rake', '>= 0.8.7')
s.add_dependency('thor', '~> 0.14.6')
s.add_dependency('rack-ssl', '~> 1.3.2')
+ s.add_dependency('rdoc', '~> 3.4')
s.add_dependency('activesupport', version)
s.add_dependency('actionpack', version)
end
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb
index 8b38081667..1c3f8a701a 100644
--- a/railties/test/abstract_unit.rb
+++ b/railties/test/abstract_unit.rb
@@ -10,7 +10,6 @@ require 'active_support/core_ext/logger'
require 'action_controller'
require 'rails/all'
-# TODO: Remove these hacks
module TestApp
class Application < Rails::Application
config.root = File.dirname(__FILE__)
diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb
index 4104bacae5..4468fa295e 100644
--- a/railties/test/application/runner_test.rb
+++ b/railties/test/application/runner_test.rb
@@ -22,6 +22,10 @@ module ApplicationTests
teardown_app
end
+ def test_should_include_runner_in_shebang_line_in_help_without_option
+ assert_match "/rails runner", Dir.chdir(app_path) { `bundle exec rails runner` }
+ end
+
def test_should_include_runner_in_shebang_line_in_help
assert_match "/rails runner", Dir.chdir(app_path) { `bundle exec rails runner --help` }
end
diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb
index 17cbac0912..dd1e4bdac1 100644
--- a/railties/test/generators/namespaced_generators_test.rb
+++ b/railties/test/generators/namespaced_generators_test.rb
@@ -7,15 +7,7 @@ require 'rails/generators/rails/scaffold/scaffold_generator'
class NamespacedGeneratorTestCase < Rails::Generators::TestCase
def setup
- TestApp::Application.isolate_namespace(TestApp)
- end
-
- def teardown
- if TestApp.respond_to?(:_railtie)
- TestApp.singleton_class.send(:undef_method, :_railtie)
- TestApp.singleton_class.send(:undef_method, :table_name_prefix)
- TestApp::Application.isolated = false
- end
+ Rails::Generators.namespace = TestApp
end
end
diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb
index b272638026..283d99dd9e 100644
--- a/railties/test/generators/plugin_new_generator_test.rb
+++ b/railties/test/generators/plugin_new_generator_test.rb
@@ -12,7 +12,6 @@ DEFAULT_PLUGIN_FILES = %w(
lib
lib/bukkits.rb
lib/tasks/bukkits_tasks.rake
- script/rails
test/bukkits_test.rb
test/test_helper.rb
test/dummy
@@ -172,6 +171,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_file "config/routes.rb", /Rails.application.routes.draw do/
assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < ::Rails::Engine\n end\nend/
assert_file "lib/bukkits.rb", /require "bukkits\/engine"/
+ assert_file "script/rails"
end
def test_being_quiet_while_creating_dummy_application
@@ -199,8 +199,16 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_file "bukkits.gemspec", /s.version = "0.0.1"/
end
+ def test_usage_of_engine_commands
+ run_generator [destination_root, "--full"]
+ assert_file "script/rails", /ENGINE_PATH = File.expand_path\('..\/..\/lib\/bukkits\/engine', __FILE__\)/
+ assert_file "script/rails", /ENGINE_ROOT = File.expand_path\('..\/..', __FILE__\)/
+ assert_file "script/rails", /require 'rails\/all'/
+ assert_file "script/rails", /require 'rails\/engine\/commands'/
+ end
+
def test_shebang
- run_generator
+ run_generator [destination_root, "--full"]
assert_file "script/rails", /#!\/usr\/bin\/env ruby/
end
@@ -254,7 +262,6 @@ class CustomPluginGeneratorTest < Rails::Generators::TestCase
assert_file 'spec/dummy'
assert_file 'Rakefile', /task :default => :spec/
assert_file 'Rakefile', /# spec tasks in rakefile/
- assert_file 'script/rails', %r{spec/dummy}
end
protected
diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb
index be9aef8a41..d3074afd91 100644
--- a/railties/test/generators/shared_generator_tests.rb
+++ b/railties/test/generators/shared_generator_tests.rb
@@ -67,12 +67,12 @@ module SharedGeneratorTests
end
def test_shebang_is_added_to_rails_file
- run_generator [destination_root, "--ruby", "foo/bar/baz"]
+ run_generator [destination_root, "--ruby", "foo/bar/baz", "--full"]
assert_file "script/rails", /#!foo\/bar\/baz/
end
def test_shebang_when_is_the_same_as_default_use_env
- run_generator [destination_root, "--ruby", Thor::Util.ruby_command]
+ run_generator [destination_root, "--ruby", Thor::Util.ruby_command, "--full"]
assert_file "script/rails", /#!\/usr\/bin\/env/
end
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 335e639692..0a203fd4d0 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -287,4 +287,4 @@ Module.new do
end
f.puts "require 'rails/all'"
end
-end
+end unless defined?(RAILS_ISOLATED_ENGINE)
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 44cee2b164..0ff1e0f180 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -15,7 +15,7 @@ module RailtiesTest
@plugin = engine "bukkits" do |plugin|
plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
railtie_name "bukkits"
end
@@ -36,7 +36,7 @@ module RailtiesTest
test "initializers are executed after application configuration initializers" do
@plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
initializer "dummy_initializer" do
end
@@ -77,7 +77,7 @@ module RailtiesTest
add_to_config("config.action_dispatch.show_exceptions = false")
@plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, ['Hello World']] }
config.middleware.use ::RailtiesTest::EngineTest::Upcaser
@@ -127,7 +127,7 @@ module RailtiesTest
test "it provides routes as default endpoint" do
@plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
end
end
@@ -153,7 +153,7 @@ module RailtiesTest
test "engine can load its own plugins" do
@plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
end
end
@@ -170,7 +170,7 @@ module RailtiesTest
test "engine does not load plugins that already exists in application" do
@plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
end
end
@@ -193,7 +193,7 @@ module RailtiesTest
test "it loads its environment file" do
@plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
end
end
@@ -212,7 +212,7 @@ module RailtiesTest
test "it passes router in env" do
@plugin.write "lib/bukkits.rb", <<-RUBY
- class Bukkits
+ module Bukkits
class Engine < ::Rails::Engine
endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, 'hello'] }
end
diff --git a/railties/test/railties/generators_test.rb b/railties/test/railties/generators_test.rb
new file mode 100644
index 0000000000..fe59dcd52b
--- /dev/null
+++ b/railties/test/railties/generators_test.rb
@@ -0,0 +1,115 @@
+RAILS_ISOLATED_ENGINE = true
+require "isolation/abstract_unit"
+
+require "#{RAILS_FRAMEWORK_ROOT}/railties/lib/rails/generators/test_case"
+
+module RailtiesTests
+ class GeneratorTest < Rails::Generators::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ TMP_PATH = File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. tmp]))
+ self.destination_root = File.join(TMP_PATH, "foo_bar")
+
+ def tmp_path(*args)
+ File.join(TMP_PATH, *args)
+ end
+
+ def engine_path
+ tmp_path('foo_bar')
+ end
+
+ def bundled_rails(cmd)
+ `bundle exec rails #{cmd}`
+ end
+
+ def rails(cmd)
+ environment = File.expand_path('../../../../load_paths', __FILE__)
+ if File.exist?("#{environment}.rb")
+ require_environment = "-r #{environment}"
+ end
+ `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/bin/rails #{cmd}`
+ end
+
+ def build_engine(is_mountable=false)
+ FileUtils.mkdir_p(engine_path)
+ FileUtils.rm_r(engine_path)
+
+ mountable = is_mountable ? "--mountable" : ""
+
+ rails("plugin new #{engine_path} --full #{mountable}")
+
+ Dir.chdir(engine_path) do
+ File.open("Gemfile", "w") do |f|
+ f.write <<-GEMFILE.gsub(/^ {12}/, '')
+ source "http://rubygems.org"
+
+ gem 'rails', :path => '#{RAILS_FRAMEWORK_ROOT}'
+ gem 'sqlite3'
+
+ if RUBY_VERSION < '1.9'
+ gem "ruby-debug", ">= 0.10.3"
+ end
+ GEMFILE
+ end
+ end
+ end
+
+ def build_mountable_engine
+ build_engine(true)
+ end
+
+ def test_controllers_are_correctly_namespaced_when_engine_is_mountable
+ build_mountable_engine
+ Dir.chdir(engine_path) do
+ bundled_rails("g controller topics")
+ assert_file "app/controllers/foo_bar/topics_controller.rb", /module FooBar\n class TopicsController/
+ assert_no_file "app/controllers/topics_controller.rb"
+ end
+ end
+
+ def test_models_are_correctly_namespaced_when_engine_is_mountable
+ build_mountable_engine
+ Dir.chdir(engine_path) do
+ bundled_rails("g model topic")
+ assert_file "app/models/foo_bar/topic.rb", /module FooBar\n class Topic/
+ assert_no_file "app/models/topic.rb"
+ end
+ end
+
+ def test_helpers_are_correctly_namespaced_when_engine_is_mountable
+ build_mountable_engine
+ Dir.chdir(engine_path) do
+ bundled_rails("g helper topics")
+ assert_file "app/helpers/foo_bar/topics_helper.rb", /module FooBar\n module TopicsHelper/
+ assert_no_file "app/helpers/topics_helper.rb"
+ end
+ end
+
+ def test_controllers_are_not_namespaced_when_engine_is_not_mountable
+ build_engine
+ Dir.chdir(engine_path) do
+ bundled_rails("g controller topics")
+ assert_file "app/controllers/topics_controller.rb", /class TopicsController/
+ assert_no_file "app/controllers/foo_bar/topics_controller.rb"
+ end
+ end
+
+ def test_models_are_not_namespaced_when_engine_is_not_mountable
+ build_engine
+ Dir.chdir(engine_path) do
+ bundled_rails("g model topic")
+ assert_file "app/models/topic.rb", /class Topic/
+ assert_no_file "app/models/foo_bar/topic.rb"
+ end
+ end
+
+ def test_helpers_are_not_namespaced_when_engine_is_not_mountable
+ build_engine
+ Dir.chdir(engine_path) do
+ bundled_rails("g helper topics")
+ assert_file "app/helpers/topics_helper.rb", /module TopicsHelper/
+ assert_no_file "app/helpers/foo_bar/topics_helper.rb"
+ end
+ end
+ end
+end
diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb
index 659551d08a..8cbc76db71 100644
--- a/railties/test/railties/shared_tests.rb
+++ b/railties/test/railties/shared_tests.rb
@@ -53,8 +53,11 @@ module RailtiesTest
add_to_config "ActiveRecord::Base.timestamped_migrations = false"
+ boot_rails
+ railties = Rails.application.railties.all.map(&:railtie_name)
+
Dir.chdir(app_path) do
- output = `rake bukkits:install:migrations`
+ output = `bundle exec rake bukkits:install:migrations`
assert File.exists?("#{app_path}/db/migrate/2_create_users.rb")
assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.rb")
@@ -63,15 +66,19 @@ module RailtiesTest
assert_match /NOTE: Migration 3_create_sessions.rb from bukkits has been skipped/, output
assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length
- output = `rake railties:install:migrations`
+ output = `bundle exec rake railties:install:migrations`.split("\n")
assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.rb")
- assert_match /NOTE: Migration 3_create_sessions.rb from bukkits has been skipped/, output
- assert_match /Copied migration 4_create_yaffles.rb from acts_as_yaffle/, output
- assert_no_match /2_create_users/, output
+ assert_no_match /2_create_users/, output.join("\n")
+
+ yaffle_migration_order = output.index(output.detect{|o| /Copied migration 4_create_yaffles.rb from acts_as_yaffle/ =~ o })
+ bukkits_migration_order = output.index(output.detect{|o| /NOTE: Migration 3_create_sessions.rb from bukkits has been skipped/ =~ o })
+ assert_not_nil yaffle_migration_order, "Expected migration to be copied"
+ assert_not_nil bukkits_migration_order, "Expected migration to be skipped"
+ assert_equal (railties.index('acts_as_yaffle') > railties.index('bukkits')) , (yaffle_migration_order > bukkits_migration_order)
migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
- output = `rake railties:install:migrations`
+ output = `bundle exec rake railties:install:migrations`
assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length
end