diff options
6 files changed, 73 insertions, 52 deletions
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 9dc47272b0..d1c8064c1b 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -260,7 +260,7 @@ module ActionView if number == 0 digits, rounded_number = 1, 0 else - digits = (Math.log10(number) + 1).floor + digits = (Math.log10(number.abs) + 1).floor rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision) end precision = precision - digits @@ -459,7 +459,7 @@ module ActionView raise ArgumentError, ":units must be a Hash or String translation scope." end.keys.map{|e_name| DECIMAL_UNITS.invert[e_name] }.sort_by{|e| -e} - number_exponent = Math.log10(number).floor + number_exponent = number != 0 ? Math.log10(number.abs).floor : 0 display_exponent = unit_exponents.find{|e| number_exponent >= e } number /= 10 ** display_exponent diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index d27cec0a29..c14dfb250f 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -83,6 +83,7 @@ class NumberHelperTest < ActionView::TestCase end def test_number_with_precision + assert_equal("-111.235", number_with_precision(-111.2346)) assert_equal("111.235", number_with_precision(111.2346)) assert_equal("31.83", number_with_precision(31.825, :precision => 2)) assert_equal("111.23", number_with_precision(111.2346, :precision => 2)) @@ -184,53 +185,55 @@ class NumberHelperTest < ActionView::TestCase end def test_number_to_human - assert_equal '123', number_to_human(123) - assert_equal '1.23 Thousand', number_to_human(1234) - assert_equal '12.3 Thousand', number_to_human(12345) - assert_equal '1.23 Million', number_to_human(1234567) - assert_equal '1.23 Billion', number_to_human(1234567890) - assert_equal '1.23 Trillion', number_to_human(1234567890123) - assert_equal '1.23 Quadrillion', number_to_human(1234567890123456) - assert_equal '1230 Quadrillion', number_to_human(1234567890123456789) - assert_equal '490 Thousand', number_to_human(489939, :precision => 2) - assert_equal '489.9 Thousand', number_to_human(489939, :precision => 4) - assert_equal '489 Thousand', number_to_human(489000, :precision => 4) - assert_equal '489.0 Thousand', number_to_human(489000, :precision => 4, :strip_insignificant_zeros => false) - assert_equal '1.2346 Million', number_to_human(1234567, :precision => 4, :significant => false) - assert_equal '1,2 Million', number_to_human(1234567, :precision => 1, :significant => false, :separator => ',') - assert_equal '1 Million', number_to_human(1234567, :precision => 0, :significant => true, :separator => ',') #significant forced to false + assert_equal '-123', number_to_human(-123) + assert_equal '0', number_to_human(0) + assert_equal '123', number_to_human(123) + assert_equal '1.23 Thousand', number_to_human(1234) + assert_equal '12.3 Thousand', number_to_human(12345) + assert_equal '1.23 Million', number_to_human(1234567) + assert_equal '1.23 Billion', number_to_human(1234567890) + assert_equal '1.23 Trillion', number_to_human(1234567890123) + assert_equal '1.23 Quadrillion', number_to_human(1234567890123456) + assert_equal '1230 Quadrillion', number_to_human(1234567890123456789) + assert_equal '490 Thousand', number_to_human(489939, :precision => 2) + assert_equal '489.9 Thousand', number_to_human(489939, :precision => 4) + assert_equal '489 Thousand', number_to_human(489000, :precision => 4) + assert_equal '489.0 Thousand', number_to_human(489000, :precision => 4, :strip_insignificant_zeros => false) + assert_equal '1.2346 Million', number_to_human(1234567, :precision => 4, :significant => false) + assert_equal '1,2 Million', number_to_human(1234567, :precision => 1, :significant => false, :separator => ',') + assert_equal '1 Million', number_to_human(1234567, :precision => 0, :significant => true, :separator => ',') #significant forced to false end def test_number_to_human_with_custom_units - #Only integers - volume = {:unit => "ml", :thousand => "lt", :million => "m3"} - assert_equal '123 lt', number_to_human(123456, :units => volume) - assert_equal '12 ml', number_to_human(12, :units => volume) - assert_equal '1.23 m3', number_to_human(1234567, :units => volume) - - #Including fractionals - distance = {:mili => "mm", :centi => "cm", :deci => "dm", :unit => "m", :ten => "dam", :hundred => "hm", :thousand => "km"} - assert_equal '1.23 mm', number_to_human(0.00123, :units => distance) - assert_equal '1.23 cm', number_to_human(0.0123, :units => distance) - assert_equal '1.23 dm', number_to_human(0.123, :units => distance) - assert_equal '1.23 m', number_to_human(1.23, :units => distance) - assert_equal '1.23 dam', number_to_human(12.3, :units => distance) - assert_equal '1.23 hm', number_to_human(123, :units => distance) - assert_equal '1.23 km', number_to_human(1230, :units => distance) - assert_equal '1.23 km', number_to_human(1230, :units => distance) - assert_equal '1.23 km', number_to_human(1230, :units => distance) - assert_equal '12.3 km', number_to_human(12300, :units => distance) - - #The quantifiers don't need to be a continuous sequence - gangster = {:hundred => "hundred bucks", :million => "thousand quids"} - assert_equal '1 hundred bucks', number_to_human(100, :units => gangster) - assert_equal '25 hundred bucks', number_to_human(2500, :units => gangster) - assert_equal '25 thousand quids', number_to_human(25000000, :units => gangster) - assert_equal '12300 thousand quids', number_to_human(12345000000, :units => gangster) - - #Spaces are stripped from the resulting string - assert_equal '4', number_to_human(4, :units => {:unit => "", :ten => 'tens '}) - assert_equal '4.5 tens', number_to_human(45, :units => {:unit => "", :ten => ' tens '}) + #Only integers + volume = {:unit => "ml", :thousand => "lt", :million => "m3"} + assert_equal '123 lt', number_to_human(123456, :units => volume) + assert_equal '12 ml', number_to_human(12, :units => volume) + assert_equal '1.23 m3', number_to_human(1234567, :units => volume) + + #Including fractionals + distance = {:mili => "mm", :centi => "cm", :deci => "dm", :unit => "m", :ten => "dam", :hundred => "hm", :thousand => "km"} + assert_equal '1.23 mm', number_to_human(0.00123, :units => distance) + assert_equal '1.23 cm', number_to_human(0.0123, :units => distance) + assert_equal '1.23 dm', number_to_human(0.123, :units => distance) + assert_equal '1.23 m', number_to_human(1.23, :units => distance) + assert_equal '1.23 dam', number_to_human(12.3, :units => distance) + assert_equal '1.23 hm', number_to_human(123, :units => distance) + assert_equal '1.23 km', number_to_human(1230, :units => distance) + assert_equal '1.23 km', number_to_human(1230, :units => distance) + assert_equal '1.23 km', number_to_human(1230, :units => distance) + assert_equal '12.3 km', number_to_human(12300, :units => distance) + + #The quantifiers don't need to be a continuous sequence + gangster = {:hundred => "hundred bucks", :million => "thousand quids"} + assert_equal '1 hundred bucks', number_to_human(100, :units => gangster) + assert_equal '25 hundred bucks', number_to_human(2500, :units => gangster) + assert_equal '25 thousand quids', number_to_human(25000000, :units => gangster) + assert_equal '12300 thousand quids', number_to_human(12345000000, :units => gangster) + + #Spaces are stripped from the resulting string + assert_equal '4', number_to_human(4, :units => {:unit => "", :ten => 'tens '}) + assert_equal '4.5 tens', number_to_human(45, :units => {:unit => "", :ten => ' tens '}) end def test_number_to_human_with_custom_format @@ -341,7 +344,7 @@ class NumberHelperTest < ActionView::TestCase end assert_raise InvalidNumberError do - number_with_delimiter("x", :raise => true) + number_with_delimiter("x", :raise => true) end begin number_with_delimiter("x", :raise => true) @@ -350,7 +353,7 @@ class NumberHelperTest < ActionView::TestCase end assert_raise InvalidNumberError do - number_to_phone("x", :raise => true) + number_to_phone("x", :raise => true) end begin number_to_phone("x", :raise => true) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 78fa85e737..6005105cc9 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -6,7 +6,7 @@ module ActiveRecord extend ActiveSupport::Concern attr_accessor :includes_values, :eager_load_values, :preload_values, - :select_values, :group_values, :order_values, :joins_values, :where_values, :having_values, + :select_values, :group_values, :order_values, :reorder_flag, :joins_values, :where_values, :having_values, :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, :from_value def includes(*args) @@ -53,7 +53,10 @@ module ActiveRecord def reorder(*args) relation = clone - relation.order_values = args if args.present? + if args.present? + relation.order_values = args + relation.reorder_flag = true + end relation end diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index e3f1496b9a..a6cf59fbf1 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -18,11 +18,20 @@ 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 + order_value = r.order_values + if order_value.present? + if r.reorder_flag + merged_relation.order_values = order_value + else + merged_relation.order_values = merged_relation.order_values + order_value + end + end + merged_relation = merged_relation.joins(r.joins_values) merged_wheres = @where_values diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index e27bb65144..f538d2a326 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -390,6 +390,12 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal expected, received end + def test_reordered_scope_overrides_default_scope_order + not_expected = DeveloperOrderedBySalary.first # Jamis -> name DESC + received = DeveloperOrderedBySalary.reordered_by_name.first # David -> name + assert not_expected.id != received.id + 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/models/developer.rb b/activerecord/test/models/developer.rb index f0d40e741b..947583af76 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -88,7 +88,7 @@ class DeveloperOrderedBySalary < ActiveRecord::Base self.table_name = 'developers' default_scope :order => 'salary DESC' scope :by_name, order('name DESC') - scope :reordered_by_name, reorder('name DESC') + scope :reordered_by_name, reorder('name') def self.all_ordered_by_name with_scope(:find => { :order => 'name DESC' }) do |