From 6c131d452389890e4253d30256b2f46afd14ed3f Mon Sep 17 00:00:00 2001 From: mynyml Date: Fri, 3 Apr 2009 20:06:48 -0400 Subject: [PATCH] Add Enumerable#every functionality. --- .../lib/active_support/core_ext/enumerable.rb | 24 ++++++++++++++++++++ .../active_support/core_ext/enumerable/proxy.rb | 13 ++++++++++ .../test/core_ext/enumerable/proxy_test.rb | 10 ++++++++ activesupport/test/core_ext/enumerable_test.rb | 10 ++++++++ 4 files changed, 57 insertions(+), 0 deletions(-) create mode 100644 activesupport/lib/active_support/core_ext/enumerable/proxy.rb create mode 100644 activesupport/test/core_ext/enumerable/proxy_test.rb diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index a7eaccf..80bebe4 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -1,6 +1,8 @@ require 'active_support/ordered_hash' module Enumerable + autoload :Proxy, 'active_support/core_ext/enumerable/proxy' + # Ruby 1.8.7 introduces group_by, but the result isn't ordered. Override it. remove_method(:group_by) if [].respond_to?(:group_by) && RUBY_VERSION < '1.9' @@ -113,4 +115,26 @@ module Enumerable def none?(&block) !any?(&block) end unless [].respond_to?(:none?) + + # Proxies a method onto each member of a collection. + # + # enum = [1.4, 2.4, 3.4] + # enum.every.floor #=> [1, 2, 3] + # + # enum = %w( axc dxf ) + # enum.every.gsub(/x/,'y') #=> ["ayc", "dyf"] + # enum.every.gsub(/x/) { 'y' } #=> ["ayc", "dyf"] + # enum.every.upcase! + # enum #=> ["AXC", "DXF"] + # + # enum = ['foo', 'bar', ''] + # enum.every.empty?.all? #=> false + # enum.every.empty?.any? #=> true + # + # @company.clients.every.name + # Company.all.every.clients.flatten.every.name + # + def every + Proxy.new(self, :map) + end end diff --git a/activesupport/lib/active_support/core_ext/enumerable/proxy.rb b/activesupport/lib/active_support/core_ext/enumerable/proxy.rb new file mode 100644 index 0000000..29b0512 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/enumerable/proxy.rb @@ -0,0 +1,13 @@ +module Enumerable + class Proxy + instance_methods.each { |m| undef_method(m) unless m.match(/^__/) } + + def initialize(enum, method=:map) + @enum, @method = enum, method + end + + def method_missing(method, *args, &block) + @enum.__send__(@method) {|o| o.__send__(method, *args, &block) } + end + end +end diff --git a/activesupport/test/core_ext/enumerable/proxy_test.rb b/activesupport/test/core_ext/enumerable/proxy_test.rb new file mode 100644 index 0000000..2001d4b --- /dev/null +++ b/activesupport/test/core_ext/enumerable/proxy_test.rb @@ -0,0 +1,10 @@ +require 'abstract_unit' + +class EnumerableProxyTests < Test::Unit::TestCase + def test_is_basic_object + whitelist = %w( __id__ __send__ method_missing __metaclass__ __is_a__ ) + i_methods = Enumerable::Proxy.instance_methods + + assert_equal whitelist.to_set, i_methods.to_set + end +end diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index 92db977..75a5207 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -90,4 +90,14 @@ class EnumerableTests < Test::Unit::TestCase assert ![ 1, 2 ].none? {|x| x > 1 } assert [ 1, 1 ].none? {|x| x > 1 } end + + def test_every + assert_equal %w( FOO BAR BAZ ), %w( foo bar baz ).every.upcase + assert_equal %w( foo xar xaz ), %w( foo bar baz ).every.gsub(/^b/,'x') + assert_equal %w( foo xar xaz ), %w( foo bar baz ).every.gsub(/^b/) { 'x' } + + enum = %w( foo bar baz ) + enum.every.upcase! + assert_equal %w( FOO BAR BAZ ), enum + end end -- 1.5.6.3