aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile4
-rw-r--r--actionmailer/actionmailer.gemspec2
-rw-r--r--actionmailer/test/abstract_unit.rb10
-rw-r--r--actionpack/actionpack.gemspec2
-rw-r--r--actionpack/lib/abstract_controller/helpers.rb22
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb52
-rw-r--r--actionpack/lib/action_controller/test_case.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb3
-rw-r--r--actionpack/lib/action_view/helpers/asset_paths.rb4
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/translation_helper.rb6
-rw-r--r--actionpack/test/controller/test_test.rb12
-rw-r--r--actionpack/test/controller/view_paths_test.rb12
-rw-r--r--actionpack/test/dispatch/prefix_generation_test.rb1
-rw-r--r--actionpack/test/template/asset_tag_helper_test.rb15
-rw-r--r--actionpack/test/template/number_helper_test.rb1
-rw-r--r--activemodel/activemodel.gemspec2
-rw-r--r--activemodel/lib/active_model/observer_array.rb126
-rw-r--r--activemodel/lib/active_model/observing.rb38
-rw-r--r--activemodel/test/cases/observer_array_test.rb161
-rw-r--r--activemodel/test/cases/observing_test.rb5
-rw-r--r--activemodel/test/models/observers.rb27
-rw-r--r--activerecord/lib/active_record/base.rb23
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb4
-rw-r--r--activerecord/lib/active_record/persistence.rb13
-rw-r--r--activerecord/lib/active_record/railties/databases.rake10
-rw-r--r--activerecord/lib/active_record/railties/jdbcmysql_error.rb16
-rw-r--r--activerecord/lib/active_record/relation.rb2
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb4
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb5
-rw-r--r--activerecord/test/cases/adapters/postgresql/datatype_test.rb25
-rw-r--r--activerecord/test/cases/base_test.rb6
-rw-r--r--activerecord/test/cases/mass_assignment_security_test.rb18
-rw-r--r--activerecord/test/cases/persistence_test.rb40
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb7
-rw-r--r--activerecord/test/cases/validations/uniqueness_validation_test.rb26
-rw-r--r--activerecord/test/schema/postgresql_specific_schema.rb10
-rw-r--r--activeresource/test/connection_test.rb2
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--activesupport/lib/active_support/buffered_logger.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb4
-rw-r--r--activesupport/lib/active_support/deprecation.rb2
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb2
-rw-r--r--activesupport/test/core_ext/array_ext_test.rb2
-rw-r--r--railties/lib/rails/application/finisher.rb4
-rw-r--r--railties/lib/rails/commands/console.rb2
-rw-r--r--railties/lib/rails/engine.rb39
-rw-r--r--railties/lib/rails/generators/app_base.rb13
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml30
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml48
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml17
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt8
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb6
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb7
-rw-r--r--railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb7
-rw-r--r--railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb7
-rw-r--r--railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb7
-rw-r--r--railties/lib/rails/generators/test_unit/model/templates/unit_test.rb7
-rw-r--r--railties/lib/rails/generators/test_unit/observer/templates/unit_test.rb7
-rw-r--r--railties/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt7
-rw-r--r--railties/test/generators/app_generator_test.rb18
-rw-r--r--railties/test/generators/plugin_new_generator_test.rb6
-rw-r--r--railties/test/railties/engine_test.rb45
67 files changed, 890 insertions, 160 deletions
diff --git a/Gemfile b/Gemfile
index c262b97819..8b6ddbd7c9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,7 +13,7 @@ gem "rack-test", :git => "git://github.com/brynary/rack-test.git"
gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git"
gem "coffee-script"
-gem "sass", ">= 3.0"
+gem "sass"
gem "uglifier"
gem "rake", ">= 0.8.7"
@@ -54,7 +54,7 @@ platforms :ruby do
group :db do
gem "pg", ">= 0.11.0"
gem "mysql", ">= 2.8.1"
- gem "mysql2", :git => "git://github.com/brianmario/mysql2.git"
+ gem "mysql2", ">= 0.3.0"
end
end
diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec
index a59069cc37..447e25ca8a 100644
--- a/actionmailer/actionmailer.gemspec
+++ b/actionmailer/actionmailer.gemspec
@@ -18,5 +18,5 @@ Gem::Specification.new do |s|
s.requirements << 'none'
s.add_dependency('actionpack', version)
- s.add_dependency('mail', '~> 2.2.16')
+ s.add_dependency('mail', '~> 2.3.0')
end
diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb
index ce664bf301..0b076e1ff9 100644
--- a/actionmailer/test/abstract_unit.rb
+++ b/actionmailer/test/abstract_unit.rb
@@ -23,11 +23,6 @@ if "ruby".encoding_aware?
end
end
-silence_warnings do
- # These external dependencies have warnings :/
- require 'mail'
-end
-
lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
@@ -35,6 +30,11 @@ require 'test/unit'
require 'action_mailer'
require 'action_mailer/test_case'
+silence_warnings do
+ # These external dependencies have warnings :/
+ require 'mail'
+end
+
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index d3c66800d9..f771737779 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
s.add_dependency('activemodel', version)
s.add_dependency('rack-cache', '~> 1.0.0')
s.add_dependency('builder', '~> 3.0.0')
- s.add_dependency('i18n', '~> 0.5.0')
+ s.add_dependency('i18n', '~> 0.6.0beta1')
s.add_dependency('rack', '~> 1.2.1')
s.add_dependency('rack-test', '~> 0.5.7')
s.add_dependency('rack-mount', '~> 0.7.1')
diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb
index 20f8601a8e..0ff1c0491a 100644
--- a/actionpack/lib/abstract_controller/helpers.rb
+++ b/actionpack/lib/abstract_controller/helpers.rb
@@ -112,17 +112,6 @@ module AbstractController
default_helper_module! unless anonymous?
end
- private
- # Makes all the (instance) methods in the helper module available to templates
- # rendered through this controller.
- #
- # ==== Parameters
- # * <tt>module</tt> - The module to include into the current helper module
- # for the class
- def add_template_helper(mod)
- _helpers.module_eval { include mod }
- end
-
# Returns a list of modules, normalized from the acceptable kinds of
# helpers with the following behavior:
#
@@ -155,6 +144,17 @@ module AbstractController
end
end
+ private
+ # Makes all the (instance) methods in the helper module available to templates
+ # rendered through this controller.
+ #
+ # ==== Parameters
+ # * <tt>module</tt> - The module to include into the current helper module
+ # for the class
+ def add_template_helper(mod)
+ _helpers.module_eval { include mod }
+ end
+
def default_helper_module!
module_name = name.sub(/Controller$/, '')
module_path = module_name.underscore
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 91a88ab68a..75757db564 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -76,35 +76,35 @@ module ActionController
@helper_proxy ||= ActionView::Base.new.extend(_helpers)
end
- private
- # Overwrite modules_for_helpers to accept :all as argument, which loads
- # all helpers in helpers_path.
- #
- # ==== Parameters
- # * <tt>args</tt> - A list of helpers
- #
- # ==== Returns
- # * <tt>array</tt> - A normalized list of modules for the list of helpers provided.
- def modules_for_helpers(args)
- args += all_application_helpers if args.delete(:all)
- super(args)
- end
+ # Overwrite modules_for_helpers to accept :all as argument, which loads
+ # all helpers in helpers_path.
+ #
+ # ==== Parameters
+ # * <tt>args</tt> - A list of helpers
+ #
+ # ==== Returns
+ # * <tt>array</tt> - A normalized list of modules for the list of helpers provided.
+ def modules_for_helpers(args)
+ args += all_application_helpers if args.delete(:all)
+ super(args)
+ end
- # Extract helper names from files in <tt>app/helpers/**/*_helper.rb</tt>
- def all_application_helpers
- all_helpers_from_path(helpers_path)
+ def all_helpers_from_path(path)
+ helpers = []
+ Array.wrap(path).each do |_path|
+ extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
+ helpers += Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
end
+ helpers.sort!
+ helpers.uniq!
+ helpers
+ end
- def all_helpers_from_path(path)
- helpers = []
- Array.wrap(path).each do |_path|
- extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
- helpers += Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
- end
- helpers.sort!
- helpers.uniq!
- helpers
- end
+ private
+ # Extract helper names from files in <tt>app/helpers/**/*_helper.rb</tt>
+ def all_application_helpers
+ all_helpers_from_path(helpers_path)
+ end
end
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index bc4f8bb9ce..0085f542aa 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -147,7 +147,9 @@ module ActionController
if value.is_a? Fixnum
value = value.to_s
elsif value.is_a? Array
- value = Result.new(value)
+ value = Result.new(value.map { |v| v.is_a?(String) ? v.dup : v })
+ elsif value.is_a? String
+ value = value.dup
end
if extra_keys.include?(key.to_sym)
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index b28f6c2297..1d09091dc7 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -275,8 +275,7 @@ module ActionDispatch
module MountedHelpers
end
- def mounted_helpers(name = :main_app)
- define_mounted_helper(name) if name
+ def mounted_helpers
MountedHelpers
end
diff --git a/actionpack/lib/action_view/helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_paths.rb
index 55a4c442fd..cb6737b94e 100644
--- a/actionpack/lib/action_view/helpers/asset_paths.rb
+++ b/actionpack/lib/action_view/helpers/asset_paths.rb
@@ -12,7 +12,7 @@ module ActionView
@controller = controller
end
- # Add the extension +ext+ if not present. Return full URLs otherwise untouched.
+ # Add the extension +ext+ if not present. Return full or scheme-relative URLs otherwise untouched.
# Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL
# roots. Rewrite the asset path for cache-busting asset ids. Include
# asset host, if configured, with the correct request protocol.
@@ -33,7 +33,7 @@ module ActionView
end
def is_uri?(path)
- path =~ %r{^[-a-z]+://|^cid:}
+ path =~ %r{^[-a-z]+://|^cid:|^//}
end
private
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index f7cb1f5b58..9bc847a1ab 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -57,7 +57,7 @@ module ActionView
# +asset_host+ to a proc like this:
#
# ActionController::Base.asset_host = Proc.new { |source|
- # "http://assets#{source.hash % 2 + 1}.example.com"
+ # "http://assets#{Digest::MD5.hexdigest(source).to_i(16) % 2 + 1}.example.com"
# }
# image_tag("rails.png")
# # => <img alt="Rails" src="http://assets1.example.com/images/rails.png?1230601161" />
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index 59e6ce878f..26ebae6546 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -5,7 +5,7 @@ module I18n
class ExceptionHandler
include Module.new {
def call(exception, locale, key, options)
- exception.is_a?(MissingTranslationData) ? super.html_safe : super
+ exception.is_a?(MissingTranslation) ? super.html_safe : super
end
}
end
@@ -17,8 +17,8 @@ module ActionView
module TranslationHelper
# Delegates to I18n#translate but also performs three additional functions.
#
- # First, it'll pass the :rescue_format => :html option to I18n so that any caught
- # MissingTranslationData exceptions will be turned into inline spans that
+ # First, it'll pass the :rescue_format => :html option to I18n so that any
+ # thrown MissingTranslation messages will be turned into inline spans that
#
# * have a "translation-missing" class set,
# * contain the missing key as a title attribute and
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index edda0d0a30..5896222a0a 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -493,6 +493,18 @@ XML
)
end
+ def test_params_passing_with_frozen_values
+ assert_nothing_raised do
+ get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze
+ end
+ parsed_params = eval(@response.body)
+ assert_equal(
+ {'controller' => 'test_test/test', 'action' => 'test_params',
+ 'frozen' => 'icy', 'frozens' => ['icy']},
+ parsed_params
+ )
+ end
+
def test_id_converted_to_string
get :test_params, :id => 20, :foo => Object.new
assert_kind_of String, @request.path_parameters['id']
diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb
index 9280a1c2d3..42356be1ea 100644
--- a/actionpack/test/controller/view_paths_test.rb
+++ b/actionpack/test/controller/view_paths_test.rb
@@ -131,8 +131,8 @@ class ViewLoadPathsTest < ActionController::TestCase
assert_equal "Hello overridden world!", @response.body
end
- def test_override_view_paths_with_custom_resolver
- resolver_class = Class.new(ActionView::PathResolver) do
+ def test_decorate_view_paths_with_custom_resolver
+ decorator_class = Class.new(ActionView::PathResolver) do
def initialize(path_set)
@path_set = path_set
end
@@ -140,7 +140,7 @@ class ViewLoadPathsTest < ActionController::TestCase
def find_all(*args)
@path_set.find_all(*args).collect do |template|
::ActionView::Template.new(
- "Customized body",
+ "Decorated body",
template.identifier,
template.handler,
{
@@ -152,12 +152,12 @@ class ViewLoadPathsTest < ActionController::TestCase
end
end
- resolver = resolver_class.new(TestController.view_paths)
- TestController.view_paths = ActionView::PathSet.new.push(resolver)
+ decorator = decorator_class.new(TestController.view_paths)
+ TestController.view_paths = ActionView::PathSet.new.push(decorator)
get :hello_world
assert_response :success
- assert_equal "Customized body", @response.body
+ assert_equal "Decorated body", @response.body
end
def test_inheritance
diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb
index 18f28deee4..b28a058250 100644
--- a/actionpack/test/dispatch/prefix_generation_test.rb
+++ b/actionpack/test/dispatch/prefix_generation_test.rb
@@ -69,6 +69,7 @@ module TestGenerationPrefix
# force draw
RailsApplication.routes
+ RailsApplication.routes.define_mounted_helper(:main_app)
class ::InsideEngineGeneratingController < ActionController::Base
include BlogEngine.routes.url_helpers
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 4a93def5a8..2abc806e97 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -66,6 +66,7 @@ class AssetTagHelperTest < ActionView::TestCase
%(auto_discovery_link_tag(:xml)) => %(<link href="http://www.example.com" rel="alternate" title="XML" type="application/xml" />),
%(auto_discovery_link_tag(:rss, :action => "feed")) => %(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />),
%(auto_discovery_link_tag(:rss, "http://localhost/feed")) => %(<link href="http://localhost/feed" rel="alternate" title="RSS" type="application/rss+xml" />),
+ %(auto_discovery_link_tag(:rss, "//localhost/feed")) => %(<link href="//localhost/feed" rel="alternate" title="RSS" type="application/rss+xml" />),
%(auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "My RSS"})) => %(<link href="http://www.example.com" rel="alternate" title="My RSS" type="application/rss+xml" />),
%(auto_discovery_link_tag(:rss, {}, {:title => "My RSS"})) => %(<link href="http://www.example.com" rel="alternate" title="My RSS" type="application/rss+xml" />),
%(auto_discovery_link_tag(nil, {}, {:type => "text/html"})) => %(<link href="http://www.example.com" rel="alternate" title="" type="text/html" />),
@@ -100,6 +101,7 @@ class AssetTagHelperTest < ActionView::TestCase
%(javascript_include_tag("http://example.com/all")) => %(<script src="http://example.com/all" type="text/javascript"></script>),
%(javascript_include_tag("http://example.com/all.js")) => %(<script src="http://example.com/all.js" type="text/javascript"></script>),
+ %(javascript_include_tag("//example.com/all.js")) => %(<script src="//example.com/all.js" type="text/javascript"></script>),
}
StylePathToTag = {
@@ -129,6 +131,7 @@ class AssetTagHelperTest < ActionView::TestCase
%(stylesheet_link_tag("http://www.example.com/styles/style")) => %(<link href="http://www.example.com/styles/style" media="screen" rel="stylesheet" type="text/css" />),
%(stylesheet_link_tag("http://www.example.com/styles/style.css")) => %(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />),
+ %(stylesheet_link_tag("//www.example.com/styles/style.css")) => %(<link href="//www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />),
}
ImagePathToTag = {
@@ -157,6 +160,7 @@ class AssetTagHelperTest < ActionView::TestCase
%(image_tag("slash..png")) => %(<img alt="Slash." src="/images/slash..png" />),
%(image_tag(".pdf.png")) => %(<img alt=".pdf" src="/images/.pdf.png" />),
%(image_tag("http://www.rubyonrails.com/images/rails.png")) => %(<img alt="Rails" src="http://www.rubyonrails.com/images/rails.png" />),
+ %(image_tag("//www.rubyonrails.com/images/rails.png")) => %(<img alt="Rails" src="//www.rubyonrails.com/images/rails.png" />),
%(image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) => %(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />),
%(image_tag("mouse.png", :mouseover => image_path("mouse_over.png"))) => %(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />),
%(image_tag("mouse.png", :alt => nil)) => %(<img src="/images/mouse.png" />)
@@ -195,6 +199,7 @@ class AssetTagHelperTest < ActionView::TestCase
%(video_tag("error.avi", "size" => "100 x 100")) => %(<video src="/videos/error.avi" />),
%(video_tag("error.avi", "size" => "x")) => %(<video src="/videos/error.avi" />),
%(video_tag("http://media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="http://media.rubyonrails.org/video/rails_blog_2.mov" />),
+ %(video_tag("//media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="//media.rubyonrails.org/video/rails_blog_2.mov" />),
%(video_tag(["multiple.ogg", "multiple.avi"])) => %(<video><source src="multiple.ogg" /><source src="multiple.avi" /></video>),
%(video_tag(["multiple.ogg", "multiple.avi"], :size => "160x120", :controls => true)) => %(<video controls="controls" height="120" width="160"><source src="multiple.ogg" /><source src="multiple.avi" /></video>)
}
@@ -217,6 +222,7 @@ class AssetTagHelperTest < ActionView::TestCase
%(audio_tag("xml.wav")) => %(<audio src="/audios/xml.wav" />),
%(audio_tag("rss.wav", :autoplay => true, :controls => true)) => %(<audio autoplay="autoplay" controls="controls" src="/audios/rss.wav" />),
%(audio_tag("http://media.rubyonrails.org/audio/rails_blog_2.mov")) => %(<audio src="http://media.rubyonrails.org/audio/rails_blog_2.mov" />),
+ %(audio_tag("//media.rubyonrails.org/audio/rails_blog_2.mov")) => %(<audio src="//media.rubyonrails.org/audio/rails_blog_2.mov" />),
}
def test_auto_discovery_link_tag
@@ -505,6 +511,10 @@ class AssetTagHelperTest < ActionView::TestCase
assert_equal %(<img alt="Rails" src="http://www.example.com/rails.png" />), image_tag("http://www.example.com/rails.png")
end
+ def test_should_skip_asset_id_on_scheme_relative_url
+ assert_equal %(<img alt="Rails" src="//www.example.com/rails.png" />), image_tag("//www.example.com/rails.png")
+ end
+
def test_should_use_preset_asset_id
ENV["RAILS_ASSET_ID"] = "4500"
assert_equal %(<img alt="Rails" src="/images/rails.png?4500" />), image_tag("rails.png")
@@ -1095,6 +1105,11 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
assert_dom_equal(%(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag("http://bar.example.com/stylesheets/style.css"))
end
+ def test_should_ignore_asset_host_on_scheme_relative_url
+ @controller.config.asset_host = "http://assets.example.com"
+ assert_dom_equal(%(<link href="//bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag("//bar.example.com/stylesheets/style.css"))
+ end
+
def test_should_wildcard_asset_host_between_zero_and_four
@controller.config.asset_host = 'http://a%d.example.com'
assert_match(%r(http://a[0123].example.com/collaboration/hieraki/images/xml.png), image_path('xml.png'))
diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index c8d50ebf75..23a7e17e65 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -32,6 +32,7 @@ class NumberHelperTest < ActionView::TestCase
assert_equal("555-1234", number_to_phone(5551234))
assert_equal("800-555-1212", number_to_phone(8005551212))
assert_equal("(800) 555-1212", number_to_phone(8005551212, {:area_code => true}))
+ assert_equal("", number_to_phone("", {:area_code => true}))
assert_equal("800 555 1212", number_to_phone(8005551212, {:delimiter => " "}))
assert_equal("(800) 555-1212 x 123", number_to_phone(8005551212, {:area_code => true, :extension => 123}))
assert_equal("800-555-1212", number_to_phone(8005551212, :extension => " "))
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
index 9f80673bb8..ce69c4a201 100644
--- a/activemodel/activemodel.gemspec
+++ b/activemodel/activemodel.gemspec
@@ -19,6 +19,6 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', version)
s.add_dependency('builder', '~> 3.0.0')
- s.add_dependency('i18n', '~> 0.5.0')
+ s.add_dependency('i18n', '~> 0.6.0beta1')
s.add_dependency('bcrypt-ruby', '~> 2.1.4')
end
diff --git a/activemodel/lib/active_model/observer_array.rb b/activemodel/lib/active_model/observer_array.rb
new file mode 100644
index 0000000000..f3b5811b81
--- /dev/null
+++ b/activemodel/lib/active_model/observer_array.rb
@@ -0,0 +1,126 @@
+require 'set'
+
+module ActiveModel
+ # Stores the enabled/disabled state of individual observers for
+ # a particular model classes.
+ class ObserverArray < Array
+ INSTANCES = Hash.new do |hash, model_class|
+ hash[model_class] = new(model_class)
+ end
+
+ def self.for(model_class)
+ return nil unless model_class < ActiveModel::Observing
+ INSTANCES[model_class]
+ end
+
+ # returns false if:
+ # - the ObserverArray for the given model's class has the given observer
+ # in its disabled_observers set.
+ # - or that is the case at any level of the model's superclass chain.
+ def self.observer_enabled?(observer, model)
+ klass = model.class
+ observer_class = observer.class
+
+ loop do
+ break unless array = self.for(klass)
+ return false if array.disabled_observers.include?(observer_class)
+ klass = klass.superclass
+ end
+
+ true # observers are enabled by default
+ end
+
+ def disabled_observers
+ @disabled_observers ||= Set.new
+ end
+
+ attr_reader :model_class
+ def initialize(model_class, *args)
+ @model_class = model_class
+ super(*args)
+ end
+
+ def disable(*observers, &block)
+ set_enablement(false, observers, &block)
+ end
+
+ def enable(*observers, &block)
+ set_enablement(true, observers, &block)
+ end
+
+ protected
+
+ def observer_class_for(observer)
+ return observer if observer.is_a?(Class)
+
+ if observer.respond_to?(:to_sym) # string/symbol
+ observer.to_s.camelize.constantize
+ else
+ raise ArgumentError, "#{observer} was not a class or a " +
+ "lowercase, underscored class name as expected."
+ end
+ end
+
+ def start_transaction
+ disabled_observer_stack.push(disabled_observers.dup)
+ each_subclass_array do |array|
+ array.start_transaction
+ end
+ end
+
+ def disabled_observer_stack
+ @disabled_observer_stack ||= []
+ end
+
+ def end_transaction
+ @disabled_observers = disabled_observer_stack.pop
+ each_subclass_array do |array|
+ array.end_transaction
+ end
+ end
+
+ def transaction
+ start_transaction
+
+ begin
+ yield
+ ensure
+ end_transaction
+ end
+ end
+
+ def each_subclass_array
+ model_class.subclasses.each do |subclass|
+ yield self.class.for(subclass)
+ end
+ end
+
+ def set_enablement(enabled, observers)
+ if block_given?
+ transaction do
+ set_enablement(enabled, observers)
+ yield
+ end
+ else
+ observers = ActiveModel::Observer.all_observers if observers == [:all]
+ observers.each do |obs|
+ klass = observer_class_for(obs)
+
+ unless klass < ActiveModel::Observer
+ raise ArgumentError.new("#{obs} does not refer to a valid observer")
+ end
+
+ if enabled
+ disabled_observers.delete(klass)
+ else
+ disabled_observers << klass
+ end
+ end
+
+ each_subclass_array do |array|
+ array.set_enablement(enabled, observers)
+ end
+ end
+ end
+ end
+end
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index 3c80d584fe..ba6be46670 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -1,8 +1,10 @@
require 'singleton'
+require 'active_model/observer_array'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/module/aliasing'
require 'active_support/core_ext/module/remove_method'
require 'active_support/core_ext/string/inflections'
+require 'active_support/core_ext/enumerable'
module ActiveModel
module Observing
@@ -30,12 +32,12 @@ module ActiveModel
# +instantiate_observers+ is called during startup, and before
# each development request.
def observers=(*values)
- @observers = values.flatten
+ observers.replace(values.flatten)
end
# Gets the current observers.
def observers
- @observers ||= []
+ @observers ||= ObserverArray.for(self)
end
# Gets the current observer instances.
@@ -68,6 +70,10 @@ module ActiveModel
observer_instances.size
end
+ def subclasses
+ @subclasses ||= []
+ end
+
protected
def instantiate_observer(observer) #:nodoc:
# string/symbol
@@ -76,13 +82,18 @@ module ActiveModel
elsif observer.respond_to?(:instance)
observer.instance
else
- raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance"
+ raise ArgumentError,
+ "#{observer} must be a lowercase, underscored class name (or an " +
+ "instance of the class itself) responding to the instance " +
+ "method. Example: Person.observers = :big_brother # calls " +
+ "BigBrother.instance"
end
end
# Notify observers when the observed class is subclassed.
def inherited(subclass)
super
+ subclasses << subclass
notify_observers :observed_class_inherited, subclass
end
end
@@ -197,6 +208,23 @@ module ActiveModel
nil
end
end
+
+ def subclasses
+ @subclasses ||= []
+ end
+
+ # List of all observer subclasses, sub-subclasses, etc.
+ # Necessary so we can disable or enable all observers.
+ def all_observers
+ subclasses.each_with_object(subclasses.dup) do |subclass, array|
+ array.concat(subclass.all_observers)
+ end
+ end
+ end
+
+ def self.inherited(subclass)
+ subclasses << subclass
+ super
end
# Start observing the declared classes and their subclasses.
@@ -210,7 +238,9 @@ module ActiveModel
# Send observed_method(object) if the method exists.
def update(observed_method, object) #:nodoc:
- send(observed_method, object) if respond_to?(observed_method)
+ if respond_to?(observed_method) && ObserverArray.observer_enabled?(self, object)
+ send(observed_method, object)
+ end
end
# Special method sent by the observed class when it is inherited.
diff --git a/activemodel/test/cases/observer_array_test.rb b/activemodel/test/cases/observer_array_test.rb
new file mode 100644
index 0000000000..38e4fd59fc
--- /dev/null
+++ b/activemodel/test/cases/observer_array_test.rb
@@ -0,0 +1,161 @@
+require 'cases/helper'
+require 'models/observers'
+
+class ObserverArrayTest < ActiveModel::TestCase
+ def teardown
+ ORM.observers.enable :all
+ Budget.observers.enable :all
+ Widget.observers.enable :all
+ end
+
+ def assert_observer_notified(model_class, observer_class)
+ observer_class.instance.before_save_invocations.clear
+ model_instance = model_class.new
+ model_instance.save
+ assert_equal [model_instance], observer_class.instance.before_save_invocations
+ end
+
+ def assert_observer_not_notified(model_class, observer_class)
+ observer_class.instance.before_save_invocations.clear
+ model_instance = model_class.new
+ model_instance.save
+ assert_equal [], observer_class.instance.before_save_invocations
+ end
+
+ test "all observers are enabled by default" do
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ test "can disable individual observers using a class constant" do
+ ORM.observers.disable WidgetObserver
+
+ assert_observer_not_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ test "can disable individual observers using a symbol" do
+ ORM.observers.disable :budget_observer
+
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_not_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ test "can disable all observers using :all" do
+ ORM.observers.disable :all
+
+ assert_observer_not_notified Widget, WidgetObserver
+ assert_observer_not_notified Budget, BudgetObserver
+ assert_observer_not_notified Widget, AuditTrail
+ assert_observer_not_notified Budget, AuditTrail
+ end
+
+ test "can disable observers on individual models without affecting observers on other models" do
+ Widget.observers.disable :all
+
+ assert_observer_not_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_not_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ test "can disable observers for the duration of a block" do
+ yielded = false
+ ORM.observers.disable :budget_observer do
+ yielded = true
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_not_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ assert yielded
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ test "can enable observers for the duration of a block" do
+ yielded = false
+ Widget.observers.disable :all
+
+ Widget.observers.enable :all do
+ yielded = true
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ assert yielded
+ assert_observer_not_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_not_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ test "raises an appropriate error when a developer accidentally enables or disables the wrong class (i.e. Widget instead of WidgetObserver)" do
+ assert_raise ArgumentError do
+ ORM.observers.enable :widget
+ end
+
+ assert_raise ArgumentError do
+ ORM.observers.enable Widget
+ end
+
+ assert_raise ArgumentError do
+ ORM.observers.disable :widget
+ end
+
+ assert_raise ArgumentError do
+ ORM.observers.disable Widget
+ end
+ end
+
+ test "allows #enable at the superclass level to override #disable at the subclass level when called last" do
+ Widget.observers.disable :all
+ ORM.observers.enable :all
+
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ test "allows #disable at the superclass level to override #enable at the subclass level when called last" do
+ Budget.observers.enable :audit_trail
+ ORM.observers.disable :audit_trail
+
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_not_notified Widget, AuditTrail
+ assert_observer_not_notified Budget, AuditTrail
+ end
+
+ test "can use the block form at different levels of the hierarchy" do
+ yielded = false
+ Widget.observers.disable :all
+
+ ORM.observers.enable :all do
+ yielded = true
+ assert_observer_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+
+ assert yielded
+ assert_observer_not_notified Widget, WidgetObserver
+ assert_observer_notified Budget, BudgetObserver
+ assert_observer_not_notified Widget, AuditTrail
+ assert_observer_notified Budget, AuditTrail
+ end
+end
+
diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb
index 63686843b6..99b1f407ae 100644
--- a/activemodel/test/cases/observing_test.rb
+++ b/activemodel/test/cases/observing_test.rb
@@ -43,6 +43,11 @@ class ObservingTest < ActiveModel::TestCase
assert ObservedModel.observers.include?(:bar), ":bar not in #{ObservedModel.observers.inspect}"
end
+ test "uses an ObserverArray so observers can be disabled" do
+ ObservedModel.observers = [:foo, :bar]
+ assert ObservedModel.observers.is_a?(ActiveModel::ObserverArray)
+ end
+
test "instantiates observer names passed as strings" do
ObservedModel.observers << 'foo_observer'
FooObserver.expects(:instance)
diff --git a/activemodel/test/models/observers.rb b/activemodel/test/models/observers.rb
new file mode 100644
index 0000000000..3729b3435e
--- /dev/null
+++ b/activemodel/test/models/observers.rb
@@ -0,0 +1,27 @@
+class ORM
+ include ActiveModel::Observing
+
+ def save
+ notify_observers :before_save
+ end
+
+ class Observer < ActiveModel::Observer
+ def before_save_invocations
+ @before_save_invocations ||= []
+ end
+
+ def before_save(record)
+ before_save_invocations << record
+ end
+ end
+end
+
+class Widget < ORM; end
+class Budget < ORM; end
+class WidgetObserver < ORM::Observer; end
+class BudgetObserver < ORM::Observer; end
+class AuditTrail < ORM::Observer
+ observe :widget, :budget
+end
+
+ORM.instantiate_observers
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 4512e8c8ad..04c12f86b6 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1621,11 +1621,11 @@ end
# Allows you to set all the attributes at once by passing in a hash with keys
# matching the attribute names (which again matches the column names).
#
- # If +guard_protected_attributes+ is true (the default), then sensitive
- # attributes can be protected from this form of mass-assignment by using
- # the +attr_protected+ macro. Or you can alternatively specify which
- # attributes *can* be accessed with the +attr_accessible+ macro. Then all the
- # attributes not included in that won't be allowed to be mass-assigned.
+ # If any attributes are protected by either +attr_protected+ or
+ # +attr_accessible+ then only settable attributes will be assigned.
+ #
+ # The +guard_protected_attributes+ argument is now deprecated, use
+ # the +assign_attributes+ method if you want to bypass mass-assignment security.
#
# class User < ActiveRecord::Base
# attr_protected :is_admin
@@ -1635,11 +1635,16 @@ end
# user.attributes = { :username => 'Phusion', :is_admin => true }
# user.username # => "Phusion"
# user.is_admin? # => false
- #
- # user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
- # user.is_admin? # => true
- def attributes=(new_attributes, guard_protected_attributes = true)
+ def attributes=(new_attributes, guard_protected_attributes = nil)
+ unless guard_protected_attributes.nil?
+ message = "the use of 'guard_protected_attributes' will be removed from the next major release of rails, " +
+ "if you want to bypass mass-assignment security then look into using assign_attributes"
+ ActiveSupport::Deprecation.warn(message)
+ end
+
return unless new_attributes.is_a?(Hash)
+
+ guard_protected_attributes ||= true
if guard_protected_attributes
assign_attributes(new_attributes)
else
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
index 5ff81aa023..70da9d5f1e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -287,10 +287,6 @@ module ActiveRecord
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
end
- def null_insert_value
- Arel.sql 'DEFAULT'
- end
-
def empty_insert_statement_value
"VALUES(DEFAULT)"
end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index 7ac72acd58..cf68ddc2da 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -1,5 +1,6 @@
# encoding: utf-8
+gem 'mysql2', '~> 0.3.0'
require 'mysql2'
module ActiveRecord
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index e2b9a5d0d9..0c2afc180b 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -98,6 +98,9 @@ module ActiveRecord
# XML type
when 'xml'
:xml
+ # tsvector type
+ when 'tsvector'
+ :tsvector
# Arrays
when /^\D+\[\]$/
:string
@@ -189,6 +192,11 @@ module ActiveRecord
options = args.extract_options!
column(args[0], 'xml', options)
end
+
+ def tsvector(*args)
+ options = args.extract_options!
+ column(args[0], 'tsvector', options)
+ end
end
ADAPTER_NAME = 'PostgreSQL'
@@ -206,7 +214,8 @@ module ActiveRecord
:date => { :name => "date" },
:binary => { :name => "bytea" },
:boolean => { :name => "boolean" },
- :xml => { :name => "xml" }
+ :xml => { :name => "xml" },
+ :tsvector => { :name => "tsvector" }
}
# Returns 'PostgreSQL' as adapter name for identification purposes.
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index e1518f9a0f..ed5006dcec 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -346,10 +346,6 @@ module ActiveRecord
alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
end
- def null_insert_value
- Arel.sql 'NULL'
- end
-
def empty_insert_statement_value
"VALUES(NULL)"
end
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index a916c88348..787ac977e0 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -136,22 +136,27 @@ module ActiveRecord
# Updates the attributes of the model from the passed-in hash and saves the
# record, all wrapped in a transaction. If the object is invalid, the saving
# will fail and false will be returned.
- def update_attributes(attributes)
+ #
+ # When updating model attributes, mass-assignment security protection is respected.
+ # If no +:as+ option is supplied then the +:default+ scope will be used.
+ # If you want to bypass the protection given by +attr_protected+ and
+ # +attr_accessible+ then you can do so using the +:without_protection+ option.
+ def update_attributes(attributes, options = {})
# The following transaction covers any possible database side-effects of the
# attributes assignment. For example, setting the IDs of a child collection.
with_transaction_returning_status do
- self.attributes = attributes
+ self.assign_attributes(attributes, options)
save
end
end
# Updates its receiver just like +update_attributes+ but calls <tt>save!</tt> instead
# of +save+, so an exception is raised if the record is invalid.
- def update_attributes!(attributes)
+ def update_attributes!(attributes, options = {})
# The following transaction covers any possible database side-effects of the
# attributes assignment. For example, setting the IDs of a child collection.
with_transaction_returning_status do
- self.attributes = attributes
+ self.assign_attributes(attributes, options)
save!
end
end
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 6b3c38cb58..7d76d7a19f 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -70,7 +70,13 @@ db_namespace = namespace :db do
@charset = ENV['CHARSET'] || 'utf8'
@collation = ENV['COLLATION'] || 'utf8_unicode_ci'
creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)}
- error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error
+ if config['adapter'] =~ /jdbc/
+ #FIXME After Jdbcmysql gives this class
+ require 'active_record/railties/jdbcmysql_error'
+ error_class = ArJdbcMySQL::Error
+ else
+ error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error
+ end
access_denied_error = 1045
begin
ActiveRecord::Base.establish_connection(config.merge('database' => nil))
@@ -94,7 +100,7 @@ db_namespace = namespace :db do
$stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset']
end
end
- when 'postgresql'
+ when /postgresql/
@encoding = config['encoding'] || ENV['CHARSET'] || 'utf8'
begin
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
diff --git a/activerecord/lib/active_record/railties/jdbcmysql_error.rb b/activerecord/lib/active_record/railties/jdbcmysql_error.rb
new file mode 100644
index 0000000000..6b9af2a0cb
--- /dev/null
+++ b/activerecord/lib/active_record/railties/jdbcmysql_error.rb
@@ -0,0 +1,16 @@
+#FIXME Remove if ArJdbcMysql will give.
+module ArJdbcMySQL
+ class Error < StandardError
+ attr_accessor :error_number, :sql_state
+
+ def initialize msg
+ super
+ @error_number = nil
+ @sql_state = nil
+ end
+
+ # Mysql gem compatibility
+ alias_method :errno, :error_number
+ alias_method :error, :message
+ end
+end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 45a7000cce..8e5f66ec1d 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -60,7 +60,7 @@ module ActiveRecord
end
if values.empty? # empty insert
- im.values = im.create_values [connection.null_insert_value], []
+ im.values = Arel.sql(connection.empty_insert_statement_value)
else
im.insert substitutes
end
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index a3d4b7f45a..57c9921ea8 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -279,8 +279,8 @@ module ActiveRecord
unless record
record = @klass.new do |r|
- r.send(:attributes=, protected_attributes_for_create, true) unless protected_attributes_for_create.empty?
- r.send(:attributes=, unprotected_attributes_for_create, false) unless unprotected_attributes_for_create.empty?
+ r.assign_attributes(protected_attributes_for_create)
+ r.assign_attributes(unprotected_attributes_for_create, :without_protection => true)
end
yield(record) if block_given?
record.save if match.instantiator == :create
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index d1225a9ed9..4db4105389 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -56,8 +56,9 @@ module ActiveRecord
column = klass.columns_hash[attribute.to_s]
value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?
- if !options[:case_sensitive] && column.text?
- relation = table[attribute].matches(value)
+ if !options[:case_sensitive] && value && column.text?
+ # will use SQL LOWER function before comparison
+ relation = table[attribute].lower.eq(table.lower(value))
else
value = klass.connection.case_sensitive_modifier(value)
relation = table[attribute].eq(value)
diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
index 5bb8fa2f93..ce08e4c6a7 100644
--- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
@@ -3,6 +3,9 @@ require "cases/helper"
class PostgresqlArray < ActiveRecord::Base
end
+class PostgresqlTsvector < ActiveRecord::Base
+end
+
class PostgresqlMoney < ActiveRecord::Base
end
@@ -34,6 +37,9 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase
@connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )")
@first_array = PostgresqlArray.find(1)
+ @connection.execute("INSERT INTO postgresql_tsvectors (text_vector) VALUES (' ''text'' ''vector'' ')")
+ @first_tsvector = PostgresqlTsvector.find(1)
+
@connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)")
@connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)")
@first_money = PostgresqlMoney.find(1)
@@ -62,6 +68,10 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase
assert_equal :string, @first_array.column_for_attribute(:nicknames).type
end
+ def test_data_type_of_tsvector_types
+ assert_equal :tsvector, @first_tsvector.column_for_attribute(:text_vector).type
+ end
+
def test_data_type_of_money_types
assert_equal :decimal, @first_money.column_for_attribute(:wealth).type
end
@@ -95,11 +105,26 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase
assert_equal '{foo,bar,baz}', @first_array.nicknames
end
+ def test_tsvector_values
+ assert_equal "'text' 'vector'", @first_tsvector.text_vector
+ end
+
def test_money_values
assert_equal 567.89, @first_money.wealth
assert_equal(-567.89, @second_money.wealth)
end
+ def test_update_tsvector
+ new_text_vector = "'new' 'text' 'vector'"
+ assert @first_tsvector.text_vector = new_text_vector
+ assert @first_tsvector.save
+ assert @first_tsvector.reload
+ assert @first_tsvector.text_vector = new_text_vector
+ assert @first_tsvector.save
+ assert @first_tsvector.reload
+ assert_equal @first_tsvector.text_vector, new_text_vector
+ end
+
def test_number_values
assert_equal 123.456, @first_number.single
assert_equal 123456.789, @first_number.double
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index ef833857ce..5ee3b2d776 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -489,6 +489,12 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal 'value2', weird.send('a$b')
end
+ def test_attributes_guard_protected_attributes_is_deprecated
+ attributes = { "title" => "An amazing title" }
+ topic = Topic.new
+ assert_deprecated { topic.send(:attributes=, attributes, false) }
+ end
+
def test_multiparameter_attributes_on_date
attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" }
topic = Topic.find(1)
diff --git a/activerecord/test/cases/mass_assignment_security_test.rb b/activerecord/test/cases/mass_assignment_security_test.rb
index 43016df479..2c051bff84 100644
--- a/activerecord/test/cases/mass_assignment_security_test.rb
+++ b/activerecord/test/cases/mass_assignment_security_test.rb
@@ -35,10 +35,10 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
p = LoosePerson.new
p.assign_attributes(attributes_hash)
- assert_equal nil, p.id
+ assert_equal nil, p.id
assert_equal 'Josh', p.first_name
- assert_equal 'male', p.gender
- assert_equal nil, p.comments
+ assert_equal 'm', p.gender
+ assert_equal nil, p.comments
end
def test_assign_attributes_skips_mass_assignment_security_protection_when_without_protection_is_used
@@ -47,7 +47,7 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
assert_equal 5, p.id
assert_equal 'Josh', p.first_name
- assert_equal 'male', p.gender
+ assert_equal 'm', p.gender
assert_equal 'rides a sweet bike', p.comments
end
@@ -57,7 +57,7 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
assert_equal nil, p.id
assert_equal 'Josh', p.first_name
- assert_equal 'male', p.gender
+ assert_equal 'm', p.gender
assert_equal nil, p.comments
end
@@ -67,7 +67,7 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
assert_equal nil, p.id
assert_equal 'Josh', p.first_name
- assert_equal 'male', p.gender
+ assert_equal 'm', p.gender
assert_equal 'rides a sweet bike', p.comments
end
@@ -77,7 +77,7 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
assert_equal nil, p.id
assert_equal 'Josh', p.first_name
- assert_equal 'male', p.gender
+ assert_equal 'm', p.gender
assert_equal nil, p.comments
end
@@ -87,7 +87,7 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
assert_equal nil, p.id
assert_equal 'Josh', p.first_name
- assert_equal 'male', p.gender
+ assert_equal 'm', p.gender
assert_equal 'rides a sweet bike', p.comments
end
@@ -107,7 +107,7 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
{
:id => 5,
:first_name => 'Josh',
- :gender => 'male',
+ :gender => 'm',
:comments => 'rides a sweet bike'
}
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 3683e3430c..b066575af8 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -491,6 +491,26 @@ class PersistencesTest < ActiveRecord::TestCase
assert_equal "The First Topic", topic.title
end
+ def test_update_attributes_as_admin
+ person = TightPerson.create({ "first_name" => 'Joshua' })
+ person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
+ person.reload
+
+ assert_equal 'Josh', person.first_name
+ assert_equal 'm', person.gender
+ assert_equal 'from NZ', person.comments
+ end
+
+ def test_update_attributes_without_protection
+ person = TightPerson.create({ "first_name" => 'Joshua' })
+ person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
+ person.reload
+
+ assert_equal 'Josh', person.first_name
+ assert_equal 'm', person.gender
+ assert_equal 'from NZ', person.comments
+ end
+
def test_update_attributes!
Reply.validates_presence_of(:title)
reply = Reply.find(2)
@@ -512,6 +532,26 @@ class PersistencesTest < ActiveRecord::TestCase
Reply.reset_callbacks(:validate)
end
+ def test_update_attributes_with_bang_as_admin
+ person = TightPerson.create({ "first_name" => 'Joshua' })
+ person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
+ person.reload
+
+ assert_equal 'Josh', person.first_name
+ assert_equal 'm', person.gender
+ assert_equal 'from NZ', person.comments
+ end
+
+ def test_update_attributestes_with_bang_without_protection
+ person = TightPerson.create({ "first_name" => 'Joshua' })
+ person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
+ person.reload
+
+ assert_equal 'Josh', person.first_name
+ assert_equal 'm', person.gender
+ assert_equal 'from NZ', person.comments
+ end
+
def test_destroyed_returns_boolean
developer = Developer.first
assert_equal false, developer.destroyed?
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 9b2c7c00df..e8f2f44189 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -203,6 +203,13 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{t.xml "data"}, output
end
end
+
+ def test_schema_dump_includes_tsvector_shorthand_definition
+ output = standard_dump
+ if %r{create_table "postgresql_tsvectors"} =~ output
+ assert_match %r{t.tsvector "text_vector"}, output
+ end
+ end
end
def test_schema_dump_keeps_large_precision_integer_columns_as_decimal
diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb
index b4f3dd034c..0f1b3667cc 100644
--- a/activerecord/test/cases/validations/uniqueness_validation_test.rb
+++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb
@@ -162,6 +162,32 @@ class UniquenessValidationTest < ActiveRecord::TestCase
end
end
+ def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars
+ Topic.validates_uniqueness_of(:title, :case_sensitive => true)
+
+ t = Topic.new("title" => "I'm unique!")
+ assert t.save, "Should save t as unique"
+
+ t2 = Topic.new("title" => "I'm %")
+ assert t2.save, "Should save t2 as unique"
+
+ t3 = Topic.new("title" => "I'm uniqu_!")
+ assert t3.save, "Should save t3 as unique"
+ end
+
+ def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars
+ Topic.validates_uniqueness_of(:title, :case_sensitive => false)
+
+ t = Topic.new("title" => "I'm unique!")
+ assert t.save, "Should save t as unique"
+
+ t2 = Topic.new("title" => "I'm %")
+ assert t2.save, "Should save t2 as unique"
+
+ t3 = Topic.new("title" => "I'm uniqu_!")
+ assert t3.save, "Should save t3 as unique"
+ end
+
def test_validate_case_sensitive_uniqueness
Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb
index f38f4f3b44..5cf9a207f3 100644
--- a/activerecord/test/schema/postgresql_specific_schema.rb
+++ b/activerecord/test/schema/postgresql_specific_schema.rb
@@ -1,6 +1,6 @@
ActiveRecord::Schema.define do
- %w(postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings
+ %w(postgresql_tsvectors postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings
postgresql_oids postgresql_xml_data_type defaults geometrics postgresql_timestamp_with_zones).each do |table_name|
execute "DROP TABLE IF EXISTS #{quote_table_name table_name}"
end
@@ -55,6 +55,14 @@ _SQL
nicknames TEXT[]
);
_SQL
+
+ execute <<_SQL
+ CREATE TABLE postgresql_tsvectors (
+ id SERIAL PRIMARY KEY,
+ text_vector tsvector
+ );
+_SQL
+
execute <<_SQL
CREATE TABLE postgresql_moneys (
id SERIAL PRIMARY KEY,
diff --git a/activeresource/test/connection_test.rb b/activeresource/test/connection_test.rb
index 6e79845aa0..7c36393cf2 100644
--- a/activeresource/test/connection_test.rb
+++ b/activeresource/test/connection_test.rb
@@ -50,7 +50,7 @@ class ConnectionTest < Test::Unit::TestCase
# 404 is a missing resource.
assert_response_raises ActiveResource::ResourceNotFound, 404
- # 405 is a missing not allowed error
+ # 405 is a method not allowed error
assert_response_raises ActiveResource::MethodNotAllowed, 405
# 409 is an optimistic locking error
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index 968d6ff4d0..37a74a9e62 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -17,5 +17,5 @@ Gem::Specification.new do |s|
s.files = Dir['CHANGELOG', 'README.rdoc', 'lib/**/*']
s.require_path = 'lib'
- s.add_dependency('multi_json', '~> 1.0.0.rc3')
+ s.add_dependency('multi_json', '~> 1.0.0')
end
diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb
index e41731f3e7..88b50fc506 100644
--- a/activesupport/lib/active_support/buffered_logger.rb
+++ b/activesupport/lib/active_support/buffered_logger.rb
@@ -41,7 +41,7 @@ module ActiveSupport
def initialize(log, level = DEBUG)
@level = level
- @buffer = {}
+ @buffer = Hash.new { |h,k| h[k] = [] }
@auto_flushing = 1
@guard = Mutex.new
@@ -100,13 +100,8 @@ module ActiveSupport
def flush
@guard.synchronize do
- unless buffer.empty?
- old_buffer = buffer
- all_content = StringIO.new
- old_buffer.each do |content|
- all_content << content
- end
- @log.write(all_content.string)
+ buffer.each do |content|
+ @log.write(content)
end
# Important to do this even if buffer was empty or else @buffer will
@@ -127,7 +122,7 @@ module ActiveSupport
end
def buffer
- @buffer[Thread.current] ||= []
+ @buffer[Thread.current]
end
def clear_buffer
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index c69a015f12..2df4fd1da1 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -3,10 +3,10 @@ class Array
#
# %w( a b c d ).from(0) # => %w( a b c d )
# %w( a b c d ).from(2) # => %w( c d )
- # %w( a b c d ).from(10) # => nil
+ # %w( a b c d ).from(10) # => %w()
# %w().from(0) # => %w()
def from(position)
- self[position..-1]
+ self[position, length] || []
end
# Returns the beginning of the array up to +position+.
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index ce0775a690..45b9dda5ca 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -9,7 +9,7 @@ module ActiveSupport
# The version the deprecated behavior will be removed, by default.
attr_accessor :deprecation_horizon
end
- self.deprecation_horizon = '3.1'
+ self.deprecation_horizon = '3.2'
# By default, warnings are not silenced and debugging is off.
self.silenced = false
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index 10675edac5..1c4dd24227 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -81,7 +81,7 @@ module ActiveSupport
# Flush all log_subscribers' logger.
def flush_all!
- flushable_loggers.each(&:flush)
+ flushable_loggers.each { |log| log.flush }
end
end
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index d7ab3ce605..0e5407bc35 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -10,7 +10,7 @@ class ArrayExtAccessTests < Test::Unit::TestCase
def test_from
assert_equal %w( a b c d ), %w( a b c d ).from(0)
assert_equal %w( c d ), %w( a b c d ).from(2)
- assert_nil %w( a b c d ).from(10)
+ assert_equal %w(), %w( a b c d ).from(10)
end
def test_to
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index bf865ce466..028c8814c4 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -41,6 +41,10 @@ module Rails
ActionDispatch::Reloader.prepare!
end
+ initializer :define_main_app_helper do |app|
+ app.routes.define_mounted_helper(:main_app)
+ end
+
initializer :eager_load! do
if config.cache_classes && !$rails_rake_task
ActiveSupport.run_load_hooks(:before_eager_load, self)
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
index 2b7faf9715..dfd3c654ff 100644
--- a/railties/lib/rails/commands/console.rb
+++ b/railties/lib/rails/commands/console.rb
@@ -51,6 +51,6 @@ module Rails
end
# Has to set the RAILS_ENV before config/application is required
-if ARGV.first && !ARGV.first.index("-") && env = ARGV.pop # has to pop the env ARGV so IRB doesn't freak
+if ARGV.first && !ARGV.first.index("-") && env = ARGV.shift # has to shift the env ARGV so IRB doesn't freak
ENV['RAILS_ENV'] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
end
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 87385814f7..6c1064c609 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -286,6 +286,27 @@ module Rails
#
# This code will use <tt>my_engine.user_path(@user)</tt> to generate the proper route.
#
+ # == Isolated engine's helpers
+ #
+ # Sometimes you may want to isolate engine, but use helpers that are defined for it.
+ # If you want to share just a few specific helpers you can add them to application's
+ # helpers in ApplicationController:
+ #
+ # class ApplicationController < ActionController::Base
+ # helper MyEngine::SharedEngineHelper
+ # end
+ #
+ # If you want to include all of the engine's helpers, you can use #helpers method on egine's
+ # instance:
+ #
+ # class ApplicationController < ActionController::Base
+ # helper MyEngine::Engine.helpers
+ # end
+ #
+ # It will include all of the helpers from engine's directory. Take into account that this does
+ # not include helpers defined in controllers with helper_method or other similar solutions,
+ # only helpers defined in helpers directory will be included.
+ #
# == Migrations & seed data
#
# Engines can have their own migrations. The default path for migrations is exactly the same
@@ -384,6 +405,24 @@ module Rails
@railties ||= self.class::Railties.new(config)
end
+ def helpers
+ @helpers ||= begin
+ helpers = Module.new
+
+ helpers_paths = if config.respond_to?(:helpers_paths)
+ config.helpers_paths
+ else
+ paths["app/helpers"].existent
+ end
+
+ all = ActionController::Base.all_helpers_from_path(helpers_paths)
+ ActionController::Base.modules_for_helpers(all).each do |mod|
+ helpers.send(:include, mod)
+ end
+ helpers
+ end
+ end
+
def app
@app ||= begin
config.middleware = config.middleware.merge_into(default_middleware_stack)
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 481fa95068..520d2c6a3a 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -10,6 +10,8 @@ module Rails
module Generators
class AppBase < Base
DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
+ JDBC_DATABASES = %w( jdbcmysql jdbcsqlite3 jdbcpostgresql )
+ DATABASES.concat(JDBC_DATABASES)
JAVASCRIPTS = %w( jquery prototype )
attr_accessor :rails_template
@@ -133,14 +135,14 @@ module Rails
gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}'
gem 'arel', :git => 'git://github.com/rails/arel.git'
gem 'rack', :git => 'git://github.com/rack/rack.git'
- gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git"
+ gem 'sprockets', :git => 'git://github.com/sstephenson/sprockets.git'
GEMFILE
elsif options.edge?
<<-GEMFILE.strip_heredoc
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'arel', :git => 'git://github.com/rails/arel.git'
gem 'rack', :git => 'git://github.com/rack/rack.git'
- gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git"
+ gem 'sprockets', :git => 'git://github.com/sstephenson/sprockets.git'
GEMFILE
else
<<-GEMFILE.strip_heredoc
@@ -150,18 +152,21 @@ module Rails
# gem 'rails', :git => 'git://github.com/rails/rails.git'
# gem 'arel', :git => 'git://github.com/rails/arel.git'
# gem 'rack', :git => 'git://github.com/rack/rack.git'
- # gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git"
+ # gem 'sprockets', :git => 'git://github.com/sstephenson/sprockets.git'
GEMFILE
end
end
def gem_for_database
- # %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
+ # %w( mysql oracle postgresql sqlite3 frontbase ibm_db jdbcmysql jdbcsqlite3 jdbcpostgresql )
case options[:database]
when "oracle" then "ruby-oci8"
when "postgresql" then "pg"
when "frontbase" then "ruby-frontbase"
when "mysql" then "mysql2"
+ when "jdbcmysql" then "activerecord-jdbcmysql-adapter"
+ when "jdbcsqlite3" then "activerecord-jdbcsqlite3-adapter"
+ when "jdbcpostgresql" then "activerecord-jdbcpostgresql-adapter"
else options[:database]
end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index 141d9fd15c..8ad64e38ed 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -6,7 +6,7 @@ source 'http://rubygems.org'
# Asset template engines
<%= "gem 'json'\n" if RUBY_VERSION < "1.9.2" -%>
-gem 'sass', '~> 3.1.0.alpha'
+gem 'sass'
gem 'coffee-script'
gem 'uglifier'
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
new file mode 100644
index 0000000000..ca807c9f3f
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml
@@ -0,0 +1,30 @@
+# MySQL. Versions 4.1 and 5.0 are recommended.
+#
+# Install the MySQL driver:
+# gem install activerecord-jdbcmysql-adapter
+#
+# And be sure to use new-style password hashing:
+# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
+development:
+ adapter: jdbcmysql
+ database: <%= app_name %>_development
+ username: root
+ password:
+ host: localhost
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: jdbcmysql
+ database: <%= app_name %>_test
+ username: root
+ password:
+ host: localhost
+
+production:
+ adapter: jdbcmysql
+ database: <%= app_name %>_production
+ username: root
+ password:
+ host: localhost
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
new file mode 100644
index 0000000000..a228aca5d2
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml
@@ -0,0 +1,48 @@
+# PostgreSQL. Versions 7.4 and 8.x are supported.
+#
+# Install the pg driver:
+# gem install pg
+# On Mac OS X with macports:
+# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
+# On Windows:
+# gem install pg
+# Choose the win32 build.
+# Install PostgreSQL and put its /bin directory on your path.
+development:
+ adapter: jdbcpostgresql
+ encoding: unicode
+ database: <%= app_name %>_development
+ username: <%= app_name %>
+ password:
+
+ # Connect on a TCP socket. Omitted by default since the client uses a
+ # domain socket that doesn't need configuration. Windows does not have
+ # domain sockets, so uncomment these lines.
+ #host: localhost
+ #port: 5432
+
+ # Schema search path. The server defaults to $user,public
+ #schema_search_path: myapp,sharedapp,public
+
+ # Minimum log levels, in increasing order:
+ # debug5, debug4, debug3, debug2, debug1,
+ # log, notice, warning, error, fatal, and panic
+ # The server defaults to notice.
+ #min_messages: warning
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: jdbcpostgresql
+ encoding: unicode
+ database: <%= app_name %>_test
+ username: <%= app_name %>
+ password:
+
+production:
+ adapter: jdbcpostgresql
+ encoding: unicode
+ database: <%= app_name %>_production
+ username: <%= app_name %>
+ password:
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
new file mode 100644
index 0000000000..30776b3b4e
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml
@@ -0,0 +1,17 @@
+# SQLite version 3.x
+# gem 'activerecord-jdbcsqlite3-adapter'
+
+development:
+ adapter: jdbcsqlite3
+ database: db/development.sqlite3
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: jdbcsqlite3
+ database: db/test.sqlite3
+
+production:
+ adapter: jdbcsqlite3
+ database: db/production.sqlite3
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
index b00f10c545..9553f3bdde 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -11,14 +11,14 @@
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
- # Specifies the header that your server uses for sending files
- # (comment out if your front-end server doesn't support this)
- config.action_dispatch.x_sendfile_header = "X-Sendfile" # Use 'X-Accel-Redirect' for nginx
-
# Compress both stylesheets and JavaScripts
config.assets.js_compressor = :uglifier
config.assets.css_compressor = :scss
+ # Specifies the header that your server uses for sending files
+ # (comment out if your front-end server doesn't support this)
+ config.action_dispatch.x_sendfile_header = "X-Sendfile" # Use 'X-Accel-Redirect' for nginx
+
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
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 12921f47b6..126aadb88d 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
@@ -13,11 +13,13 @@ module Rails
directory "app"
template "#{app_templates_dir}/app/views/layouts/application.html.erb.tt",
"app/views/layouts/#{name}/application.html.erb"
+ empty_directory_with_gitkeep "app/assets/images"
elsif full?
empty_directory_with_gitkeep "app/models"
empty_directory_with_gitkeep "app/controllers"
empty_directory_with_gitkeep "app/views"
empty_directory_with_gitkeep "app/helpers"
+ empty_directory_with_gitkeep "app/assets/images"
end
end
@@ -199,6 +201,10 @@ task :default => :test
build(:javascripts)
end
+ def create_images_directory
+ build(:images)
+ end
+
def create_script_files
build(:script)
end
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb
index dd4d2da4eb..824caecb24 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb
@@ -5,9 +5,8 @@ class NavigationTest < ActionDispatch::IntegrationTest
fixtures :all
<% end -%>
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
end
diff --git a/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb
index 11a73ebad7..0bc5fd8ca2 100644
--- a/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/controller/templates/functional_test.rb
@@ -3,10 +3,9 @@ require 'test_helper'
<% module_namespacing do -%>
class <%= class_name %>ControllerTest < ActionController::TestCase
<% if actions.empty? -%>
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
<% else -%>
<% for action in actions -%>
test "should get <%= action %>" do
diff --git a/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb b/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb
index de0823749c..e7a06e4a73 100644
--- a/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb
+++ b/railties/lib/rails/generators/test_unit/integration/templates/integration_test.rb
@@ -3,8 +3,7 @@ require 'test_helper'
class <%= class_name %>Test < ActionDispatch::IntegrationTest
fixtures :all
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
end
diff --git a/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb
index b62c7fd279..c05102290c 100644
--- a/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/mailer/templates/functional_test.rb
@@ -13,10 +13,9 @@ class <%= class_name %>Test < ActionMailer::TestCase
<% end -%>
<% if actions.blank? -%>
- # replace this with your real tests
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
<% end -%>
end
<% end -%>
diff --git a/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb b/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb
index 6f79879838..c9bc7d5b90 100644
--- a/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb
+++ b/railties/lib/rails/generators/test_unit/model/templates/unit_test.rb
@@ -2,9 +2,8 @@ require 'test_helper'
<% module_namespacing do -%>
class <%= class_name %>Test < ActiveSupport::TestCase
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
end
<% end -%>
diff --git a/railties/lib/rails/generators/test_unit/observer/templates/unit_test.rb b/railties/lib/rails/generators/test_unit/observer/templates/unit_test.rb
index cd116f5ce9..28aa23626a 100644
--- a/railties/lib/rails/generators/test_unit/observer/templates/unit_test.rb
+++ b/railties/lib/rails/generators/test_unit/observer/templates/unit_test.rb
@@ -2,9 +2,8 @@ require 'test_helper'
<% module_namespacing do -%>
class <%= class_name %>ObserverTest < ActiveSupport::TestCase
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
end
<% end -%>
diff --git a/railties/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt b/railties/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt
index 3e0bc29d3a..0cbae1120e 100644
--- a/railties/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt
+++ b/railties/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt
@@ -1,8 +1,7 @@
require 'test_helper'
class <%= class_name %>Test < ActiveSupport::TestCase
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 58febfd9c7..1902484301 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -131,6 +131,24 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "Gemfile", /^gem\s+["']mysql2["']$/
end
+ def test_config_jdbcmysql_database
+ run_generator([destination_root, "-d", "jdbcmysql"])
+ assert_file "config/database.yml", /jdbcmysql/
+ assert_file "Gemfile", /^gem\s+["']activerecord-jdbcmysql-adapter["']$/
+ end
+
+ def test_config_jdbcsqlite3_database
+ run_generator([destination_root, "-d", "jdbcsqlite3"])
+ assert_file "config/database.yml", /jdbcsqlite3/
+ assert_file "Gemfile", /^gem\s+["']activerecord-jdbcsqlite3-adapter["']$/
+ end
+
+ def test_config_jdbcpostgresql_database
+ run_generator([destination_root, "-d", "jdbcpostgresql"])
+ assert_file "config/database.yml", /jdbcpostgresql/
+ assert_file "Gemfile", /^gem\s+["']activerecord-jdbcpostgresql-adapter["']$/
+ end
+
def test_generator_if_skip_active_record_is_given
run_generator [destination_root, "--skip-active-record"]
assert_no_file "config/database.yml"
diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb
index d20335ad95..fb956a8335 100644
--- a/railties/test/generators/plugin_new_generator_test.rb
+++ b/railties/test/generators/plugin_new_generator_test.rb
@@ -140,13 +140,14 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
run_generator [destination_root, "--full", "--skip_active_record"]
FileUtils.cd destination_root
`bundle install`
- assert_match(/2 tests, 2 assertions, 0 failures, 0 errors/, `bundle exec rake test`)
+ assert_match(/1 tests, 1 assertions, 0 failures, 0 errors/, `bundle exec rake test`)
end
def test_creating_engine_in_full_mode
run_generator [destination_root, "--full"]
assert_file "app/assets/javascripts"
assert_file "app/assets/stylesheets"
+ assert_file "app/assets/images"
assert_file "app/models"
assert_file "app/controllers"
assert_file "app/views"
@@ -162,6 +163,9 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
def test_create_mountable_application_with_mountable_option
run_generator [destination_root, "--mountable"]
+ assert_file "app/assets/javascripts"
+ assert_file "app/assets/stylesheets"
+ assert_file "app/assets/images"
assert_file "config/routes.rb", /Bukkits::Engine.routes.draw do/
assert_file "lib/bukkits/engine.rb", /isolate_namespace Bukkits/
assert_file "test/dummy/config/routes.rb", /mount Bukkits::Engine => "\/bukkits"/
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 7605984684..0c588ba773 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -584,6 +584,51 @@ module RailtiesTest
assert_equal Bukkits::Engine.instance, Rails::Engine.find(engine_path)
end
+ test "gather isolated engine's helpers in Engine#helpers" do
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ class Engine < ::Rails::Engine
+ isolate_namespace Bukkits
+ end
+ end
+ RUBY
+
+ app_file "app/helpers/some_helper.rb", <<-RUBY
+ module SomeHelper
+ def foo
+ 'foo'
+ end
+ end
+ RUBY
+
+ @plugin.write "app/helpers/bukkits/engine_helper.rb", <<-RUBY
+ module Bukkits
+ module EngineHelper
+ def bar
+ 'bar'
+ end
+ end
+ end
+ RUBY
+
+ @plugin.write "app/helpers/engine_helper.rb", <<-RUBY
+ module EngineHelper
+ def baz
+ 'baz'
+ end
+ end
+ RUBY
+
+ add_to_config("config.action_dispatch.show_exceptions = false")
+
+ boot_rails
+ require "#{rails_root}/config/environment"
+
+ methods = Bukkits::Engine.helpers.public_instance_methods.collect(&:to_s).sort
+ expected = ["bar", "baz"]
+ assert_equal expected, methods
+ end
+
private
def app
Rails.application