aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md18
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb174
-rw-r--r--actionpack/lib/action_view/helpers/record_tag_helper.rb2
-rw-r--r--actionpack/test/template/record_tag_helper_test.rb6
-rw-r--r--activerecord/lib/active_record/railties/databases.rake12
-rw-r--r--activerecord/test/cases/adapters/postgresql/connection_test.rb2
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb1
-rw-r--r--activesupport/lib/active_support/message_encryptor.rb1
-rw-r--r--activesupport/test/ordered_hash_test.rb1
9 files changed, 139 insertions, 78 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index a2cf94fb42..82438cb766 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,23 @@
## Rails 4.0.0 (unreleased) ##
+* Fix `content_tag_for` with array html option.
+ It would embed array as string instead of joining it like `content_tag` does:
+
+ content_tag(:td, class: ["foo", "bar"]){}
+ #=> '<td class="foo bar"></td>'
+
+ Before:
+
+ content_tag_for(:td, item, class: ["foo", "bar"])
+ #=> '<td class="item [&quot;foo&quot;, &quot;bar&quot;]" id="item_1"></td>'
+
+ After:
+
+ content_tag_for(:td, item, class: ["foo", "bar"])
+ #=> '<td class="item foo bar" id="item_1"></td>'
+
+ *Semyon Perepelitsa*
+
* Remove `BestStandardsSupport` middleware, !DOCTYPE html already triggers
standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx
and ChromeFrame header has been moved to `config.action_dispatch.default_headers`
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 705314f8ab..e9d34314d3 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -100,25 +100,7 @@ module ActionDispatch
def initialize
@routes = {}
@helpers = []
- @module = Module.new do
- protected
-
- def handle_positional_args(args, options, segment_keys)
- inner_options = args.extract_options!
- result = options.dup
-
- if args.size > 0
- keys = segment_keys
- if args.size < keys.size - 1 # take format into account
- keys -= self.url_options.keys if self.respond_to?(:url_options)
- keys -= options.keys
- end
- result.merge!(Hash[keys.zip(args)])
- end
-
- result.merge!(inner_options)
- end
- end
+ @module = Module.new
end
def helper_names
@@ -160,68 +142,126 @@ module ActionDispatch
routes.length
end
- private
+ class UrlHelper # :nodoc:
+ def self.create(route, options)
+ if optimize_helper?(route)
+ OptimizedUrlHelper.new(route, options)
+ else
+ new route, options
+ end
+ end
- def define_named_route_methods(name, route)
- define_url_helper route, :"#{name}_path",
- route.defaults.merge(:use_route => name, :only_path => true)
- define_url_helper route, :"#{name}_url",
- route.defaults.merge(:use_route => name, :only_path => false)
+ def self.optimize_helper?(route)
+ route.requirements.except(:controller, :action).empty?
end
- # Create a url helper allowing ordered parameters to be associated
- # with corresponding dynamic segments, so you can do:
- #
- # foo_url(bar, baz, bang)
- #
- # Instead of:
- #
- # foo_url(bar: bar, baz: baz, bang: bang)
- #
- # Also allow options hash, so you can do:
- #
- # foo_url(bar, baz, bang, sort_by: 'baz')
- #
- def define_url_helper(route, name, options)
- @module.remove_possible_method name
- @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- def #{name}(*args)
- if #{optimize_helper?(route)} && args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation?
- options = #{options.inspect}
- options.merge!(url_options) if respond_to?(:url_options)
- options[:path] = "#{optimized_helper(route)}"
- ActionDispatch::Http::URL.url_for(options)
- else
- url_for(handle_positional_args(args, #{options.inspect}, #{route.segment_keys.inspect}))
- end
+ class OptimizedUrlHelper < UrlHelper # :nodoc:
+ attr_reader :arg_size
+
+ def initialize(route, options)
+ super
+ @path_parts = @route.required_parts
+ @arg_size = @path_parts.size
+ @string_route = string_route(route)
+ end
+
+ def call(t, args)
+ if args.size == arg_size && !args.last.is_a?(Hash) && optimize_routes_generation?(t)
+ @options.merge!(t.url_options) if t.respond_to?(:url_options)
+ @options[:path] = optimized_helper(args)
+ ActionDispatch::Http::URL.url_for(@options)
+ else
+ super
+ end
+ end
+
+ private
+
+ def string_route(route)
+ string_route = route.ast.to_s.dup
+ while string_route.gsub!(/\([^\)]*\)/, "")
+ true
+ end
+ string_route
+ end
+
+ def optimized_helper(args)
+ path = @string_route.dup
+ klass = Journey::Router::Utils
+
+ @path_parts.zip(args) do |part, arg|
+ # Replace each route parameter
+ # e.g. :id for regular parameter or *path for globbing
+ # with ruby string interpolation code
+ path.gsub!(/(\*|:)#{part}/, klass.escape_fragment(arg.to_param))
end
- END_EVAL
+ path
+ end
- helpers << name
+ def optimize_routes_generation?(t)
+ t.send(:optimize_routes_generation?)
+ end
end
- # Clause check about when we need to generate an optimized helper.
- def optimize_helper?(route) #:nodoc:
- route.requirements.except(:controller, :action).empty?
+ def initialize(route, options)
+ @options = options
+ @segment_keys = route.segment_keys
+ @route = route
+ end
+
+ def call(t, args)
+ t.url_for(handle_positional_args(t, args, @options, @segment_keys))
end
- # Generates the interpolation to be used in the optimized helper.
- def optimized_helper(route)
- string_route = route.ast.to_s
+ def handle_positional_args(t, args, options, keys)
+ inner_options = args.extract_options!
+ result = options.dup
- while string_route.gsub!(/\([^\)]*\)/, "")
- true
+ if args.size > 0
+ if args.size < keys.size - 1 # take format into account
+ keys -= t.url_options.keys if t.respond_to?(:url_options)
+ keys -= options.keys
+ end
+ result.merge!(Hash[keys.zip(args)])
end
- route.required_parts.each_with_index do |part, i|
- # Replace each route parameter
- # e.g. :id for regular parameter or *path for globbing
- # with ruby string interpolation code
- string_route.gsub!(/(\*|:)#{part}/, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}")
- end
+ result.merge!(inner_options)
+ end
+ end
+
+ private
+ # Create a url helper allowing ordered parameters to be associated
+ # with corresponding dynamic segments, so you can do:
+ #
+ # foo_url(bar, baz, bang)
+ #
+ # Instead of:
+ #
+ # foo_url(bar: bar, baz: baz, bang: bang)
+ #
+ # Also allow options hash, so you can do:
+ #
+ # foo_url(bar, baz, bang, sort_by: 'baz')
+ #
+ def define_url_helper(route, name, options)
+ helper = UrlHelper.create(route, options.dup)
- string_route
+ @module.remove_possible_method name
+ @module.module_eval do
+ define_method(name) do |*args|
+ helper.call self, args
+ end
end
+
+ helpers << name
+ end
+
+ def define_named_route_methods(name, route)
+ define_url_helper route, :"#{name}_path",
+ route.defaults.merge(:use_route => name, :only_path => true)
+ define_url_helper route, :"#{name}_url",
+ route.defaults.merge(:use_route => name, :only_path => false)
+ end
end
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb
index 271a194913..f767957fa9 100644
--- a/actionpack/lib/action_view/helpers/record_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb
@@ -92,7 +92,7 @@ module ActionView
# for each record.
def content_tag_for_single_record(tag_name, record, prefix, options, &block)
options = options ? options.dup : {}
- options[:class] = "#{dom_class(record, prefix)} #{options[:class]}".rstrip
+ options[:class] = [ dom_class(record, prefix), options[:class] ].compact
options[:id] = dom_id(record, prefix)
if block_given?
diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb
index 9c49438f6a..ab84bccb56 100644
--- a/actionpack/test/template/record_tag_helper_test.rb
+++ b/actionpack/test/template/record_tag_helper_test.rb
@@ -41,6 +41,12 @@ class RecordTagHelperTest < ActionView::TestCase
assert_dom_equal expected, actual
end
+ def test_content_tag_for_with_array_css_class
+ expected = %(<tr class="record_tag_post special odd" id="record_tag_post_45"></tr>)
+ actual = content_tag_for(:tr, @post, class: ["special", "odd"])
+ assert_dom_equal expected, actual
+ end
+
def test_content_tag_for_with_prefix_and_extra_html_options
expected = %(<tr class="archived_record_tag_post special" id="archived_record_tag_post_45" style='background-color: #f0f0f0'></tr>)
actual = content_tag_for(:tr, @post, :archived, class: "special", style: "background-color: #f0f0f0")
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 259d0ff12b..f36af7182f 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -284,8 +284,6 @@ db_namespace = namespace :db do
filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql")
current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
case current_config['adapter']
- when /mysql/, /postgresql/, /sqlite/
- ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
when 'oci', 'oracle'
ActiveRecord::Base.establish_connection(current_config)
File.open(filename, "w:utf-8") { |f| f << ActiveRecord::Base.connection.structure_dump }
@@ -296,7 +294,7 @@ db_namespace = namespace :db do
db_string = firebird_db_string(current_config)
sh "isql -a #{db_string} > #{filename}"
else
- raise "Task not supported by '#{current_config["adapter"]}'"
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
end
if ActiveRecord::Base.connection.supports_migrations?
@@ -312,8 +310,6 @@ db_namespace = namespace :db do
current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql")
case current_config['adapter']
- when /mysql/, /postgresql/, /sqlite/
- ActiveRecord::Tasks::DatabaseTasks.structure_load(current_config, filename)
when 'sqlserver'
`sqlcmd -S #{current_config['host']} -d #{current_config['database']} -U #{current_config['username']} -P #{current_config['password']} -i #{filename}`
when 'oci', 'oracle'
@@ -326,7 +322,7 @@ db_namespace = namespace :db do
db_string = firebird_db_string(current_config)
sh "isql -i #{filename} #{db_string}"
else
- raise "Task not supported by '#{current_config['adapter']}'"
+ ActiveRecord::Tasks::DatabaseTasks.structure_load(current_config, filename)
end
end
@@ -384,8 +380,6 @@ db_namespace = namespace :db do
task :purge => [:environment, :load_config] do
abcs = ActiveRecord::Base.configurations
case abcs['test']['adapter']
- when /mysql/, /postgresql/, /sqlite/
- ActiveRecord::Tasks::DatabaseTasks.purge abcs['test']
when 'sqlserver'
test = abcs.deep_dup['test']
test_database = test['database']
@@ -401,7 +395,7 @@ db_namespace = namespace :db do
ActiveRecord::Base.establish_connection(:test)
ActiveRecord::Base.connection.recreate_database!
else
- raise "Task not supported by '#{abcs['test']['adapter']}'"
+ ActiveRecord::Tasks::DatabaseTasks.purge abcs['test']
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb
index fa8f339f00..c03660957e 100644
--- a/activerecord/test/cases/adapters/postgresql/connection_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb
@@ -108,7 +108,7 @@ module ActiveRecord
@connection.verify!
new_connection_pid = @connection.query('select pg_backend_pid()')
ensure
- raw_connection_class.class_eval <<-CODE
+ raw_connection_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
alias query query_unfake
undef query_fake
CODE
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index c7dbfc95dc..512296554f 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -7,6 +7,7 @@ end
require 'digest/md5'
require 'active_support/core_ext/marshal'
+require 'active_support/core_ext/array/extract_options'
module ActiveSupport
module Cache
diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb
index b7dc0689b0..ce40a7d689 100644
--- a/activesupport/lib/active_support/message_encryptor.rb
+++ b/activesupport/lib/active_support/message_encryptor.rb
@@ -1,5 +1,6 @@
require 'openssl'
require 'base64'
+require 'active_support/core_ext/array/extract_options'
module ActiveSupport
# MessageEncryptor is a simple way to encrypt values which get stored
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index 14ba4e0076..6aea9d56f1 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -2,6 +2,7 @@ require 'abstract_unit'
require 'active_support/json'
require 'active_support/core_ext/object/to_json'
require 'active_support/core_ext/hash/indifferent_access'
+require 'active_support/core_ext/array/extract_options'
class OrderedHashTest < ActiveSupport::TestCase
def setup