diff --git a/activesupport/lib/active_support/core_ext/range/conversions.rb b/activesupport/lib/active_support/core_ext/range/conversions.rb index 932bded..627c076 100644 --- a/activesupport/lib/active_support/core_ext/range/conversions.rb +++ b/activesupport/lib/active_support/core_ext/range/conversions.rb @@ -4,7 +4,7 @@ module ActiveSupport #:nodoc: # Getting ranges in different convenient string representations and other objects module Conversions RANGE_FORMATS = { - :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" } + :db => Proc.new { |range| "BETWEEN '#{range.first.to_s(:db)}' AND '#{range.last.to_s(:db)}'" } } def self.included(base) #:nodoc: @@ -13,13 +13,34 @@ module ActiveSupport #:nodoc: alias_method :to_s, :to_formatted_s end end + # Gives a human readable format of the range. # + # This method is aliased to to_s. + # # ==== Example: # - # [1..100].to_formatted_s # => "1..100" + # (1..100).to_formatted_s # => "1..100" + # (Date.today..Date.tomorrow).to_s(:db) # => "BETWEEN '2008-12-31' AND '2009-01-01'" + # + # == Adding your own range formats to +to_formatted_s+ + # You can add your own formats to the Range::RANGE_FORMATS hash. + # Use the format name as the hash key and a Proc instance + # that takes a range argument as the value. + # + # # config/initializers/range_formats.rb + # Range::RANGE_FORMATS[:lucene] = lambda { |range| "[#{range.first} TO #{range.last}]" } def to_formatted_s(format = :default) - RANGE_FORMATS[format] ? RANGE_FORMATS[format].call(first, last) : to_default_s + format = RANGE_FORMATS[format] + + if format.nil? + to_default_s + elsif format.arity == 2 + ActiveSupport::Deprecation.warn('Range#to_formatted_s now prefers to pass the range itself into the format block, rather than first and last', caller) + format.call(first, last) + else + format.call(self) + end end end end diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index 38253d4..4e1c357 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class RangeTest < Test::Unit::TestCase +class RangeTest < ActiveSupport::TestCase def test_to_s_from_dates date_range = Date.new(2005, 12, 10)..Date.new(2005, 12, 12) assert_equal "BETWEEN '2005-12-10' AND '2005-12-12'", date_range.to_s(:db) @@ -10,6 +10,26 @@ class RangeTest < Test::Unit::TestCase date_range = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30) assert_equal "BETWEEN '2005-12-10 15:30:00' AND '2005-12-10 17:30:00'", date_range.to_s(:db) end + + def test_to_s_passes_first_and_last_to_arity_2 + Range::RANGE_FORMATS.merge!(:report_first_and_last => Proc.new {|first, last| [first, last].inspect }) + + assert_deprecated("Range#to_formatted_s now prefers to pass the range itself into the format block, rather than first and last.") do + assert_equal '["Aida", "Carmen"]', ("Aida".."Carmen").to_s(:report_first_and_last) + end + end + + def test_to_s_passes_self_to_arity_1 + Range::RANGE_FORMATS.merge!(:report_self => Proc.new {|range| range.inspect }) + + assert_equal '"Aida".."Carmen"', ("Aida".."Carmen").to_s(:report_self) + end + + def test_to_s_passes_self_to_splat + Range::RANGE_FORMATS.merge!(:report_splat => Proc.new {|*args| args.map(&:inspect).join }) + + assert_equal '"Aida".."Carmen"', ("Aida".."Carmen").to_s(:report_splat) + end def test_overlaps_last_inclusive assert((1..5).overlaps?(5..10))