diff options
39 files changed, 178 insertions, 245 deletions
diff --git a/RELEASING_RAILS.rdoc b/RELEASING_RAILS.rdoc index 7bad1d01b8..7a77f9bba2 100644 --- a/RELEASING_RAILS.rdoc +++ b/RELEASING_RAILS.rdoc @@ -25,12 +25,6 @@ for Rails. You can check the status of his tests here: Do not release with Red AWDwR tests. -=== Are the postgres tests green? If not, make them green - -Currently Travis CI doesn't run the Active Record postgres tests. They are -working to resolve this, but in the mean time, it is crucial to ensure that -the tests are still green before release. - === Do we have any git dependencies? If so, contact those authors. Having git dependencies indicates that we depend on unreleased code. @@ -66,8 +60,6 @@ for today: === Is Sam Ruby happy? If not, make him happy. -=== Are the postgres tests green? If not, make them green - === Contact the security team. CVE emails must be sent on this day. === Create a release branch. diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index d46ee4faef..1e4bebeee7 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1093,7 +1093,7 @@ module ActionView end hidden = tag("input", "name" => options["name"], "type" => "hidden", "value" => options['disabled'] && checked ? checked_value : unchecked_value) checkbox = tag("input", options) - (hidden + checkbox).html_safe + hidden + checkbox end def to_boolean_select_tag(options = {}) diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 3db1394df7..43122ef2ba 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -127,6 +127,7 @@ module ActionView defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {}) currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :default => {}) + currency[:negative_format] ||= "-" + currency[:format] if currency[:format] defaults = DEFAULT_CURRENCY_VALUES.merge(defaults).merge!(currency) defaults[:negative_format] = "-" + options[:format] if options[:format] diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 73b936b16e..6fe4ce65cf 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -330,6 +330,7 @@ class FormHelperTest < ActionView::TestCase end def test_check_box + assert check_box("post", "secret").html_safe? assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb index 5df09b4d3b..d6e9de9555 100644 --- a/actionpack/test/template/number_helper_i18n_test.rb +++ b/actionpack/test/template/number_helper_i18n_test.rb @@ -53,6 +53,13 @@ class NumberHelperTest < ActionView::TestCase assert_equal("-$10.00", number_to_currency(-10)) end end + + def test_number_to_currency_without_currency_negative_format + clean_i18n do + I18n.backend.store_translations 'ts', :number => { :currency => { :format => { :unit => '@', :format => '%n %u' } } } + assert_equal("-10.00 @", number_to_currency(-10, :locale => 'ts')) + end + end def test_number_with_i18n_precision #Delimiter was set to "" diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb index 9b12d9d281..13495d6786 100644 --- a/activemodel/lib/active_model/mass_assignment_security.rb +++ b/activemodel/lib/active_model/mass_assignment_security.rb @@ -1,6 +1,5 @@ require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/string/inflections' -require 'active_support/core_ext/array/wrap' require 'active_model/mass_assignment_security/permission_set' require 'active_model/mass_assignment_security/sanitizer' @@ -116,7 +115,7 @@ module ActiveModel self._protected_attributes = protected_attributes_configs.dup - Array.wrap(role).each do |name| + Array(role).each do |name| self._protected_attributes[name] = self.protected_attributes(name) + args end @@ -178,7 +177,7 @@ module ActiveModel self._accessible_attributes = accessible_attributes_configs.dup - Array.wrap(role).each do |name| + Array(role).each do |name| self._accessible_attributes[name] = self.accessible_attributes(name) + args end diff --git a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb index bbdddfb50d..cfeb4aa7cd 100644 --- a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb +++ b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb @@ -1,11 +1,6 @@ -require 'active_support/core_ext/module/delegation' - module ActiveModel module MassAssignmentSecurity class Sanitizer - def initialize(target=nil) - end - # Returns all attributes not denied by the authorizer. def sanitize(attributes, authorizer) sanitized_attributes = attributes.reject { |key, value| authorizer.deny?(key) } @@ -26,11 +21,13 @@ module ActiveModel end class LoggerSanitizer < Sanitizer - delegate :logger, :to => :@target - def initialize(target) @target = target - super + super() + end + + def logger + @target.logger end def logger? @@ -38,14 +35,18 @@ module ActiveModel end def process_removed_attributes(attrs) - logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger? + logger.warn "Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger? end end class StrictSanitizer < Sanitizer + def initialize(target = nil) + super() + end + def process_removed_attributes(attrs) return if (attrs - insensitive_attributes).empty? - raise ActiveModel::MassAssignmentSecurity::Error, "Can't mass-assign protected attributes: #{attrs.join(', ')}" + raise ActiveModel::MassAssignmentSecurity::Error.new(attrs) end def insensitive_attributes @@ -54,6 +55,9 @@ module ActiveModel end class Error < StandardError + def initialize(attrs) + super("Can't mass-assign protected attributes: #{attrs.join(', ')}") + end end end end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index d29cf82dad..d4d0220fb7 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'set' require 'active_support/benchmarkable' @@ -12,7 +7,6 @@ require 'active_support/time' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/class/delegating_attributes' -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/hash/deep_merge' require 'active_support/core_ext/hash/indifferent_access' diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index d2361b5378..cf86caa21e 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -11,20 +11,20 @@ module ActiveRecord # Establishes a connection to the database that's used by all Active Record objects def postgresql_connection(config) # :nodoc: config = config.symbolize_keys - host = config[:host] - port = config[:port] || 5432 - username = config[:username].to_s if config[:username] - password = config[:password].to_s if config[:password] - if config.key?(:database) - database = config[:database] - else - raise ArgumentError, "No database specified. Missing argument: database." - end + # Forward any unused config params to PGconn.connect. + conn_params = config.except(:statement_limit, :encoding, :min_messages, + :schema_search_path, :schema_order, + :adapter, :pool, :wait_timeout) + conn_params.delete_if { |k,v| v.nil? } + + # Map ActiveRecords param names to PGs. + conn_params[:user] = conn_params.delete(:username) if conn_params[:username] + conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database] # The postgres drivers don't allow the creation of an unconnected PGconn object, # so just pass a nil connection object for the time being. - ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, [host, port, nil, nil, database, username, password], config) + ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, conn_params, config) end end @@ -226,22 +226,29 @@ module ActiveRecord end end - # The PostgreSQL adapter works both with the native C (http://ruby.scripting.ca/postgres/) and the pure - # Ruby (available both as gem and from http://rubyforge.org/frs/?group_id=234&release_id=1944) drivers. + # The PostgreSQL adapter works with the native C (https://bitbucket.org/ged/ruby-pg) driver. # # Options: # - # * <tt>:host</tt> - Defaults to "localhost". + # * <tt>:host</tt> - Defaults to a Unix-domain socket in /tmp. On machines without Unix-domain sockets, + # the default is to connect to localhost. # * <tt>:port</tt> - Defaults to 5432. - # * <tt>:username</tt> - Defaults to nothing. - # * <tt>:password</tt> - Defaults to nothing. - # * <tt>:database</tt> - The name of the database. No default, must be provided. + # * <tt>:username</tt> - Defaults to be the same as the operating system name of the user running the application. + # * <tt>:password</tt> - Password to be used if the server demands password authentication. + # * <tt>:database</tt> - Defaults to be the same as the user name. # * <tt>:schema_search_path</tt> - An optional schema search path for the connection given # as a string of comma-separated schema names. This is backward-compatible with the <tt>:schema_order</tt> option. # * <tt>:encoding</tt> - An optional client encoding that is used in a <tt>SET client_encoding TO # <encoding></tt> call on the connection. # * <tt>:min_messages</tt> - An optional client min messages that is used in a # <tt>SET client_min_messages TO <min_messages></tt> call on the connection. + # + # Any further options are used as connection parameters to libpq. See + # http://www.postgresql.org/docs/9.1/static/libpq-connect.html for the + # list of parameters. + # + # In addition, default connection parameters of libpq can be set per environment variables. + # See http://www.postgresql.org/docs/9.1/static/libpq-envars.html . class PostgreSQLAdapter < AbstractAdapter class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition def xml(*args) @@ -1200,7 +1207,7 @@ module ActiveRecord # Connects to a PostgreSQL server and sets up the adapter depending on the # connected server's characteristics. def connect - @connection = PGconn.connect(*@connection_parameters) + @connection = PGconn.connect(@connection_parameters) # Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of # PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 980f8fe50f..0755379a74 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -317,26 +317,6 @@ module ActiveRecord "#<#{self.class} #{inspection}>" end - # Hackery to accomodate Syck. Remove for 4.0. - def to_yaml(opts = {}) #:nodoc: - if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? - super - else - coder = {} - encode_with(coder) - YAML.quick_emit(self, opts) do |out| - out.map(taguri, to_yaml_style) do |map| - coder.each { |k, v| map.add(k, v) } - end - end - end - end - - # Hackery to accomodate Syck. Remove for 4.0. - def yaml_initialize(tag, coder) #:nodoc: - init_with(coder) - end - private # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 9ea8cf864c..339ba1e19e 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -1,10 +1,4 @@ require 'erb' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'zlib' require 'active_support/dependencies' diff --git a/activerecord/lib/active_record/fixtures/file.rb b/activerecord/lib/active_record/fixtures/file.rb index 6bad36abb9..6547791144 100644 --- a/activerecord/lib/active_record/fixtures/file.rb +++ b/activerecord/lib/active_record/fixtures/file.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'erb' require 'yaml' diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 6f2248fa21..bf1de4ba9d 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -8,7 +8,7 @@ module ActiveRecord JoinOperation = Struct.new(:relation, :join_class, :on) ASSOCIATION_METHODS = [:includes, :eager_load, :preload] MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] - SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] + SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq] include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index e58c726e09..f1ac421a50 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -134,7 +134,7 @@ module ActiveRecord def last(*args) if args.any? if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash)) - if order_values.empty? && reorder_value.nil? + if order_values.empty? order("#{primary_key} DESC").limit(*args).reverse else to_a.last(*args) @@ -249,7 +249,7 @@ module ActiveRecord end def construct_limited_ids_condition(relation) - orders = (relation.reorder_value || relation.order_values).map { |val| val.presence }.compact + orders = relation.order_values.map { |val| val.presence }.compact values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) relation = relation.dup diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index c281bead0d..456afbb4cf 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -9,7 +9,7 @@ module ActiveRecord :select_values, :group_values, :order_values, :joins_values, :where_values, :having_values, :bind_values, :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, - :from_value, :reorder_value, :reverse_order_value, + :from_value, :reordering_value, :reverse_order_value, :uniq_value def includes(*args) @@ -97,7 +97,8 @@ module ActiveRecord return self if args.blank? relation = clone - relation.reorder_value = args.flatten + relation.reordering_value = true + relation.order_values = args.flatten relation end @@ -263,7 +264,7 @@ module ActiveRecord arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? - order = @reorder_value ? @reorder_value : @order_values + order = @order_values order = reverse_sql_order(order) if @reverse_order_value arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty? diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index a5194beae5..de639a48f2 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -22,7 +22,7 @@ module ActiveRecord end end - (Relation::MULTI_VALUE_METHODS - [:joins, :where]).each do |method| + (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method| value = r.send(:"#{method}_values") merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present? end @@ -48,7 +48,7 @@ module ActiveRecord merged_relation.where_values = merged_wheres - (Relation::SINGLE_VALUE_METHODS - [:lock, :create_with]).each do |method| + (Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method| value = r.send(:"#{method}_value") merged_relation.send(:"#{method}_value=", value) unless value.nil? end @@ -57,6 +57,15 @@ module ActiveRecord merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty? + if (r.reordering_value) + # override any order specified in the original relation + merged_relation.reordering_value = true + merged_relation.order_values = r.order_values + else + # merge in order_values from r + merged_relation.order_values += r.order_values + end + # Apply scope extension modules merged_relation.send :apply_modules, r.extensions diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index cdde5cf3b9..2a565b51c6 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -112,7 +112,7 @@ HEADER # AR has an optimization which handles zero-scale decimals as integers. This # code ensures that the dumper still dumps the column as a decimal. - spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) } + spec[:type] = if column.type == :integer && /^(numeric|decimal)/ =~ column.sql_type 'decimal' else column.type.to_s @@ -127,10 +127,14 @@ HEADER end.compact # find all migration keys used in this table - keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map{ |k| k.keys }.flatten + keys = [:name, :limit, :precision, :scale, :default, :null] # figure out the lengths for each column based on above keys - lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max } + lengths = keys.map { |key| + column_specs.map { |spec| + spec[key] ? spec[key].length + 2 : 0 + }.max + } # the string we're going to sprintf our values against, with standardized column widths format_string = lengths.map{ |len| "%-#{len}s" } diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index 5398a14fc6..64ecef2077 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -9,6 +9,10 @@ module ActiveRecord cleanup_identity_map end + def teardown + ActiveRecord::SQLCounter.log.clear + end + def cleanup_identity_map ActiveRecord::IdentityMap.clear end @@ -49,5 +53,9 @@ module ActiveRecord ensure ActiveRecord::SQLCounter.ignored_sql = prev_ignored_sql end + + def sqlite3? connection + connection.class.name.split('::').last == "SQLite3Adapter" + end end end diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index 21b97b3b39..4baec749ff 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -2,6 +2,9 @@ require "cases/helper" module ActiveRecord class PostgresqlConnectionTest < ActiveRecord::TestCase + class NonExistentTable < ActiveRecord::Base + end + def setup super @connection = ActiveRecord::Base.connection @@ -10,5 +13,17 @@ module ActiveRecord def test_encoding assert_not_nil @connection.encoding end + + # Ensure, we can set connection params using the example of Generic + # Query Optimizer (geqo). It is 'on' per default. + def test_connection_options + params = ActiveRecord::Base.connection_config.dup + params[:options] = "-c geqo=off" + NonExistentTable.establish_connection(params) + + # Verify the connection param has been applied. + expect = NonExistentTable.connection.query('show geqo').first.first + assert_equal 'off', expect + end end end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 4c3f2bda57..1376810adf 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -586,6 +586,7 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning') end @@ -908,6 +909,7 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning') end @@ -1031,6 +1033,7 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @ship = Ship.create(:name => 'Nights Dirty Lightning') @pirate = @ship.create_pirate(:catchphrase => "Don' botharrr talkin' like one, savvy?") end @@ -1279,6 +1282,7 @@ class TestAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @association_name = :birds @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @@ -1293,6 +1297,7 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @association_name = :parrots @habtm = true @@ -1308,6 +1313,7 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @pirate.birds.create(:name => 'cookoo') end @@ -1324,6 +1330,7 @@ class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::Tes self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @pirate.create_ship(:name => 'titanic') super @@ -1346,6 +1353,7 @@ class TestAutosaveAssociationValidationsOnABelongsToAssociation < ActiveRecord:: self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") end @@ -1366,6 +1374,7 @@ class TestAutosaveAssociationValidationsOnAHABTMAssociation < ActiveRecord::Test self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") end @@ -1388,6 +1397,7 @@ class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCas self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.new end diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index 8b4638b161..c65d073835 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -421,6 +421,12 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal expected, received end + def test_order_after_reorder_combines_orders + expected = Developer.order('name DESC, id DESC').collect { |dev| [dev.name, dev.id] } + received = Developer.order('name ASC').reorder('name DESC').order('id DESC').collect { |dev| [dev.name, dev.id] } + assert_equal expected, received + end + def test_nested_exclusive_scope expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary } received = DeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 15cb7aec07..e9a3b0419c 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -20,7 +20,7 @@ module ActiveRecord end def test_single_values - assert_equal [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq].map(&:to_s).sort, + assert_equal [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq].map(&:to_s).sort, Relation::SINGLE_VALUE_METHODS.map(&:to_s).sort end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index dd6d7e52d5..724632489b 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -3,6 +3,7 @@ require "cases/helper" class SchemaDumperTest < ActiveRecord::TestCase def setup + super @stream = StringIO.new end diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb index 2b4ec81199..302913e095 100644 --- a/activerecord/test/cases/yaml_serialization_test.rb +++ b/activerecord/test/cases/yaml_serialization_test.rb @@ -1,4 +1,4 @@ -require "cases/helper" +require 'cases/helper' require 'models/topic' class YamlSerializationTest < ActiveRecord::TestCase @@ -36,22 +36,17 @@ class YamlSerializationTest < ActiveRecord::TestCase assert_equal({'attributes' => topic.attributes}, coder) end - begin - require 'psych' - - def test_psych_roundtrip - topic = Topic.first - assert topic - t = Psych.load Psych.dump topic - assert_equal topic, t - end - - def test_psych_roundtrip_new_object - topic = Topic.new - assert topic - t = Psych.load Psych.dump topic - assert_equal topic.attributes, t.attributes - end - rescue LoadError + def test_psych_roundtrip + topic = Topic.first + assert topic + t = Psych.load Psych.dump topic + assert_equal topic, t + end + + def test_psych_roundtrip_new_object + topic = Topic.new + assert topic + t = Psych.load Psych.dump topic + assert_equal topic.attributes, t.attributes end end diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index df3aeb6b8a..0495741c15 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -77,8 +77,8 @@ module ActiveSupport # save # end # - def run_callbacks(kind, key = nil, &block) - self.class.__run_callbacks(key, kind, self, &block) + def run_callbacks(kind, *args, &block) + send("_run_#{kind}_callbacks", *args, &block) end private @@ -376,12 +376,24 @@ module ActiveSupport end module ClassMethods + # Generate the internal runner method called by +run_callbacks+. + def __define_runner(symbol) #:nodoc: + runner_method = "_run_#{symbol}_callbacks" + unless private_method_defined?(runner_method) + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def #{runner_method}(key = nil, &blk) + self.class.__run_callback(key, :#{symbol}, self, &blk) + end + private :#{runner_method} + RUBY_EVAL + end + end # This method calls the callback method for the given key. # If this called first time it creates a new callback method for the key, # calculating which callbacks can be omitted because of per_key conditions. # - def __run_callbacks(key, kind, object, &blk) #:nodoc: + def __run_callback(key, kind, object, &blk) #:nodoc: name = __callback_runner_name(key, kind) unless object.respond_to?(name) str = send("_#{kind}_callbacks").compile(key, object) @@ -606,6 +618,7 @@ module ActiveSupport callbacks.each do |callback| class_attribute "_#{callback}_callbacks" send("_#{callback}_callbacks=", CallbackChain.new(callback, config)) + __define_runner(callback) end end end diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb index 391bdc925d..3ec7e576c8 100644 --- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb +++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb @@ -1,29 +1,9 @@ require 'bigdecimal' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' class BigDecimal - YAML_TAG = 'tag:yaml.org,2002:float' YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' } - # This emits the number without any scientific notation. - # This is better than self.to_f.to_s since it doesn't lose precision. - # - # Note that reconstituting YAML floats to native floats may lose precision. - def to_yaml(opts = {}) - return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - - YAML.quick_emit(nil, opts) do |out| - string = to_s - out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain) - end - end - def encode_with(coder) string = to_s coder.represent_scalar(nil, YAML_MAPPING[string] || string) diff --git a/activesupport/lib/active_support/core_ext/class/subclasses.rb b/activesupport/lib/active_support/core_ext/class/subclasses.rb index 46e9daaa8f..74ea047c24 100644 --- a/activesupport/lib/active_support/core_ext/class/subclasses.rb +++ b/activesupport/lib/active_support/core_ext/class/subclasses.rb @@ -7,7 +7,7 @@ class Class #:nodoc: def descendants descendants = [] - ObjectSpace.each_object(class << self; self; end) do |k| + ObjectSpace.each_object(singleton_class) do |k| descendants.unshift k unless k == self end descendants diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index d478ee0ef6..1a34e88a87 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -36,14 +36,13 @@ class String # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)") # # => "And they f... (continued)" def truncate(length, options = {}) - text = self.dup - options[:omission] ||= "..." + return self.dup unless self.length > length - length_with_room_for_omission = length - options[:omission].mb_chars.length - chars = text.mb_chars + options[:omission] ||= "..." + length_with_room_for_omission = length - options[:omission].length stop = options[:separator] ? - (chars.rindex(options[:separator].mb_chars, length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission + (rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission - (chars.length > length ? chars[0...stop] + options[:omission] : text).to_s + self[0...stop] + options[:omission] end end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 6cb2ea68b3..73aa7dd89a 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -136,11 +136,6 @@ module ActiveSupport #:nodoc: coder.represent_scalar nil, to_str end - def to_yaml(*args) - return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - to_str.to_yaml(*args) - end - UNSAFE_STRING_METHODS.each do |unsafe_method| if 'String'.respond_to?(unsafe_method) class_eval <<-EOT, __FILE__, __LINE__ + 1 diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index f3235d11bb..5e433f5dd9 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -78,7 +78,7 @@ class Time options[:hour] || hour, options[:min] || (options[:hour] ? 0 : min), options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec), - options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : usec) + options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000)) ) end diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb index f9505a247c..80dcaf5613 100644 --- a/activesupport/lib/active_support/deprecation/behaviors.rb +++ b/activesupport/lib/active_support/deprecation/behaviors.rb @@ -34,8 +34,8 @@ module ActiveSupport if defined?(Rails) && Rails.logger Rails.logger else - require 'logger' - Logger.new($stderr) + require 'active_support/logger' + ActiveSupport::Logger.new($stderr) end logger.warn message logger.debug callstack.join("\n ") if debug diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index d4f309fbd7..8edd3960c7 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'yaml' YAML.add_builtin_type("omap") do |type, val| @@ -29,20 +24,6 @@ module ActiveSupport coder.represent_seq '!omap', map { |k,v| { k => v } } end - def to_yaml(opts = {}) - if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? - return super - end - - YAML.quick_emit(self, opts) do |out| - out.seq(taguri) do |seq| - each do |k, v| - seq.add(k => v) - end - end - end - end - def nested_under_indifferent_access self end diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb index 6b29ba4c10..c896b955fb 100644 --- a/activesupport/lib/active_support/testing/isolation.rb +++ b/activesupport/lib/active_support/testing/isolation.rb @@ -38,11 +38,7 @@ module ActiveSupport end def self.included(base) - if defined?(::MiniTest) && base < ::MiniTest::Unit::TestCase - base.send :include, MiniTest - elsif defined?(Test::Unit) - base.send :include, TestUnit - end + base.send :include, MiniTest end def _run_class_setup # class setup method should only happen in parent @@ -52,30 +48,6 @@ module ActiveSupport end end - module TestUnit - def run(result) - _run_class_setup - - yield(Test::Unit::TestCase::STARTED, name) - - @_result = result - - serialized = run_in_isolation do |proxy| - begin - super(proxy) { } - rescue Exception => e - proxy.add_error(Test::Unit::Error.new(name, e)) - end - end - - retval, proxy = Marshal.load(serialized) - proxy.__replay__(@_result) - - yield(Test::Unit::TestCase::FINISHED, name) - retval - end - end - module MiniTest def run(runner) _run_class_setup diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index d3adf671a0..1cb71012ef 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -1,4 +1,4 @@ -require "active_support/values/time_zone" +require 'active_support/values/time_zone' require 'active_support/core_ext/object/acts_like' require 'active_support/core_ext/object/inclusion' @@ -146,12 +146,6 @@ module ActiveSupport end end - def to_yaml(options = {}) - return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - - utc.to_yaml(options) - end - def httpdate utc.httpdate end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 6cc63851e9..1c22a79d75 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -491,6 +491,11 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.utc(2013,10,17,20,22,19), Time.utc(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5, :hours => 5, :minutes => 7, :seconds => 9) end + def test_advance_with_nsec + t = Time.at(0, Rational(108635108, 1000)) + assert_equal t, t.advance(:months => 0) + end + def test_prev_week with_env_tz 'US/Eastern' do assert_equal Time.local(2005,2,21), Time.local(2005,3,1,15,15,10).prev_week diff --git a/activesupport/test/isolation_test.rb b/activesupport/test/isolation_test.rb index 2c2986ea28..c1932d73d9 100644 --- a/activesupport/test/isolation_test.rb +++ b/activesupport/test/isolation_test.rb @@ -80,26 +80,6 @@ else ENV.delete("CHILD") def setup - defined?(::MiniTest) ? parse_minitest : parse_testunit - end - - def parse_testunit - @results = {} - OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result| - result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$' - @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2] - end - - # Extract the backtraces - @backtraces = {} - OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace| - # \n 1) Error:\ntest_captures_errors(ChildIsolationTest): - backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i - @backtraces[$2] = { :type => $1, :output => backtrace } - end - end - - def parse_minitest @results = {} OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result| result =~ %r'^\w+#(\w+):.*:\s*(.*Assertion.*|.*RuntimeError.*|\.\s*)$' @@ -115,7 +95,7 @@ else OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace| # \n 1) Error:\ntest_captures_errors(ChildIsolationTest): backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i - @backtraces[$2] = { :type => $1, :output => backtrace } + @backtraces[$2] = {:type => $1, :output => backtrace} end end diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 8119b36491..78de7fb6ab 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -291,21 +291,16 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal @ordered_hash.values, @deserialized_ordered_hash.values end - begin - require 'psych' + def test_psych_serialize + @deserialized_ordered_hash = Psych.load(Psych.dump(@ordered_hash)) - def test_psych_serialize - @deserialized_ordered_hash = Psych.load(Psych.dump(@ordered_hash)) - - values = @deserialized_ordered_hash.map { |_, value| value } - assert_equal @values, values - end + values = @deserialized_ordered_hash.map { |_, value| value } + assert_equal @values, values + end - def test_psych_serialize_tag - yaml = Psych.dump(@ordered_hash) - assert_match '!omap', yaml - end - rescue LoadError + def test_psych_serialize_tag + yaml = Psych.dump(@ordered_hash) + assert_match '!omap', yaml end def test_has_yaml_tag diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 8f77999d25..2fde07995b 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -1,9 +1,4 @@ require 'abstract_unit' -begin - require 'psych' -rescue LoadError -end - require 'active_support/core_ext/string/inflections' require 'yaml' @@ -96,13 +91,20 @@ class SafeBufferTest < ActiveSupport::TestCase assert !@buffer.dup.html_safe? end + test "Should return safe buffer when added with another safe buffer" do + clean = "<script>".html_safe + result_buffer = @buffer + clean + assert result_buffer.html_safe? + assert_equal "<script>", result_buffer + end + test "Should raise an error when safe_concat is called on dirty buffers" do @buffer.gsub!('', '<>') assert_raise ActiveSupport::SafeBuffer::SafeConcatError do @buffer.safe_concat "BUSTED" end end - + test "should not fail if the returned object is not a string" do assert_kind_of NilClass, @buffer.slice("chipchop") end diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index d425c9db6c..6fc127efae 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -1,10 +1,4 @@ require 'erb' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'optparse' require 'rbconfig' |