/activesupport/test/core_ext/module_test.rb
Ruby | 509 lines | 455 code | 51 blank | 3 comment | 0 complexity | ac225ebeb4076005169a55fb70475953 MD5 | raw file
- require 'abstract_unit'
- require 'active_support/core_ext/module'
- module One
- Constant1 = "Hello World"
- Constant2 = "What's up?"
- end
- class Ab
- include One
- Constant1 = "Hello World" # Will have different object id than One::Constant1
- Constant3 = "Goodbye World"
- end
- module Yz
- module Zy
- class Cd
- include One
- end
- end
- end
- Somewhere = Struct.new(:street, :city) do
- attr_accessor :name
- end
- class Someone < Struct.new(:name, :place)
- delegate :street, :city, :to_f, :to => :place
- delegate :name=, :to => :place, :prefix => true
- delegate :upcase, :to => "place.city"
- delegate :table_name, :to => :class
- delegate :table_name, :to => :class, :prefix => true
- def self.table_name
- 'some_table'
- end
- FAILED_DELEGATE_LINE = __LINE__ + 1
- delegate :foo, :to => :place
- FAILED_DELEGATE_LINE_2 = __LINE__ + 1
- delegate :bar, :to => :place, :allow_nil => true
- end
- Invoice = Struct.new(:client) do
- delegate :street, :city, :name, :to => :client, :prefix => true
- delegate :street, :city, :name, :to => :client, :prefix => :customer
- end
- Project = Struct.new(:description, :person) do
- delegate :name, :to => :person, :allow_nil => true
- delegate :to_f, :to => :description, :allow_nil => true
- end
- Developer = Struct.new(:client) do
- delegate :name, :to => :client, :prefix => nil
- end
- Event = Struct.new(:case) do
- delegate :foo, :to => :case
- end
- Tester = Struct.new(:client) do
- delegate :name, :to => :client, :prefix => false
- def foo; 1; end
- end
- Product = Struct.new(:name) do
- delegate :name, :to => :manufacturer, :prefix => true
- delegate :name, :to => :type, :prefix => true
- def manufacturer
- @manufacturer ||= begin
- nil.unknown_method
- end
- end
- def type
- @type ||= begin
- nil.type_name
- end
- end
- end
- class ParameterSet
- delegate :[], :[]=, :to => :@params
- def initialize
- @params = {:foo => "bar"}
- end
- end
- class Name
- delegate :upcase, :to => :@full_name
- def initialize(first, last)
- @full_name = "#{first} #{last}"
- end
- end
- class SideEffect
- attr_reader :ints
- delegate :to_i, :to => :shift, :allow_nil => true
- delegate :to_s, :to => :shift
- def initialize
- @ints = [1, 2, 3]
- end
- def shift
- @ints.shift
- end
- end
- class ModuleTest < ActiveSupport::TestCase
- def setup
- @david = Someone.new("David", Somewhere.new("Paulina", "Chicago"))
- end
- def test_delegation_to_methods
- assert_equal "Paulina", @david.street
- assert_equal "Chicago", @david.city
- end
- def test_delegation_to_assignment_method
- @david.place_name = "Fred"
- assert_equal "Fred", @david.place.name
- end
- def test_delegation_to_index_get_method
- @params = ParameterSet.new
- assert_equal "bar", @params[:foo]
- end
- def test_delegation_to_index_set_method
- @params = ParameterSet.new
- @params[:foo] = "baz"
- assert_equal "baz", @params[:foo]
- end
- def test_delegation_down_hierarchy
- assert_equal "CHICAGO", @david.upcase
- end
- def test_delegation_to_instance_variable
- david = Name.new("David", "Hansson")
- assert_equal "DAVID HANSSON", david.upcase
- end
- def test_delegation_to_class_method
- assert_equal 'some_table', @david.table_name
- assert_equal 'some_table', @david.class_table_name
- end
- def test_missing_delegation_target
- assert_raise(ArgumentError) do
- Name.send :delegate, :nowhere
- end
- assert_raise(ArgumentError) do
- Name.send :delegate, :noplace, :tos => :hollywood
- end
- end
- def test_delegation_prefix
- invoice = Invoice.new(@david)
- assert_equal invoice.client_name, "David"
- assert_equal invoice.client_street, "Paulina"
- assert_equal invoice.client_city, "Chicago"
- end
- def test_delegation_custom_prefix
- invoice = Invoice.new(@david)
- assert_equal invoice.customer_name, "David"
- assert_equal invoice.customer_street, "Paulina"
- assert_equal invoice.customer_city, "Chicago"
- end
- def test_delegation_prefix_with_nil_or_false
- assert_equal Developer.new(@david).name, "David"
- assert_equal Tester.new(@david).name, "David"
- end
- def test_delegation_prefix_with_instance_variable
- assert_raise ArgumentError do
- Class.new do
- def initialize(client)
- @client = client
- end
- delegate :name, :address, :to => :@client, :prefix => true
- end
- end
- end
- def test_delegation_with_allow_nil
- rails = Project.new("Rails", Someone.new("David"))
- assert_equal rails.name, "David"
- end
- def test_delegation_with_allow_nil_and_nil_value
- rails = Project.new("Rails")
- assert_nil rails.name
- end
- # Ensures with check for nil, not for a falseish target.
- def test_delegation_with_allow_nil_and_false_value
- project = Project.new(false, false)
- assert_raise(NoMethodError) { project.name }
- end
- def test_delegation_with_allow_nil_and_invalid_value
- rails = Project.new("Rails", "David")
- assert_raise(NoMethodError) { rails.name }
- end
- def test_delegation_with_allow_nil_and_nil_value_and_prefix
- Project.class_eval do
- delegate :name, :to => :person, :allow_nil => true, :prefix => true
- end
- rails = Project.new("Rails")
- assert_nil rails.person_name
- end
- def test_delegation_without_allow_nil_and_nil_value
- david = Someone.new("David")
- assert_raise(Module::DelegationError) { david.street }
- end
- def test_delegation_to_method_that_exists_on_nil
- nil_person = Someone.new(nil)
- assert_equal 0.0, nil_person.to_f
- end
- def test_delegation_to_method_that_exists_on_nil_when_allowing_nil
- nil_project = Project.new(nil)
- assert_equal 0.0, nil_project.to_f
- end
- def test_delegation_does_not_raise_error_when_removing_singleton_instance_methods
- parent = Class.new do
- def self.parent_method; end
- end
- assert_nothing_raised do
- Class.new(parent) do
- class << self
- delegate :parent_method, :to => :superclass
- end
- end
- end
- end
- def test_delegation_line_number
- _, line = Someone.instance_method(:foo).source_location
- assert_equal Someone::FAILED_DELEGATE_LINE, line
- end
- def test_delegate_line_with_nil
- _, line = Someone.instance_method(:bar).source_location
- assert_equal Someone::FAILED_DELEGATE_LINE_2, line
- end
- def test_delegation_exception_backtrace
- someone = Someone.new("foo", "bar")
- someone.foo
- rescue NoMethodError => e
- file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE}"
- # We can't simply check the first line of the backtrace, because JRuby reports the call to __send__ in the backtrace.
- assert e.backtrace.any?{|a| a.include?(file_and_line)},
- "[#{e.backtrace.inspect}] did not include [#{file_and_line}]"
- end
- def test_delegation_exception_backtrace_with_allow_nil
- someone = Someone.new("foo", "bar")
- someone.bar
- rescue NoMethodError => e
- file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE_2}"
- # We can't simply check the first line of the backtrace, because JRuby reports the call to __send__ in the backtrace.
- assert e.backtrace.any?{|a| a.include?(file_and_line)},
- "[#{e.backtrace.inspect}] did not include [#{file_and_line}]"
- end
- def test_delegation_invokes_the_target_exactly_once
- se = SideEffect.new
- assert_equal 1, se.to_i
- assert_equal [2, 3], se.ints
- assert_equal '2', se.to_s
- assert_equal [3], se.ints
- end
- def test_delegation_doesnt_mask_nested_no_method_error_on_nil_receiver
- product = Product.new('Widget')
- # Nested NoMethodError is a different name from the delegation
- assert_raise(NoMethodError) { product.manufacturer_name }
- # Nested NoMethodError is the same name as the delegation
- assert_raise(NoMethodError) { product.type_name }
- end
- def test_parent
- assert_equal Yz::Zy, Yz::Zy::Cd.parent
- assert_equal Yz, Yz::Zy.parent
- assert_equal Object, Yz.parent
- end
- def test_parents
- assert_equal [Yz::Zy, Yz, Object], Yz::Zy::Cd.parents
- assert_equal [Yz, Object], Yz::Zy.parents
- end
- def test_local_constants
- assert_equal %w(Constant1 Constant3), Ab.local_constants.sort.map(&:to_s)
- end
- end
- module BarMethodAliaser
- def self.included(foo_class)
- foo_class.class_eval do
- include BarMethods
- alias_method_chain :bar, :baz
- end
- end
- end
- module BarMethods
- def bar_with_baz
- bar_without_baz << '_with_baz'
- end
- def quux_with_baz!
- quux_without_baz! << '_with_baz'
- end
- def quux_with_baz?
- false
- end
- def quux_with_baz=(v)
- send(:quux_without_baz=, v) << '_with_baz'
- end
- def duck_with_orange
- duck_without_orange << '_with_orange'
- end
- end
- class MethodAliasingTest < ActiveSupport::TestCase
- def setup
- Object.const_set :FooClassWithBarMethod, Class.new { def bar() 'bar' end }
- @instance = FooClassWithBarMethod.new
- end
- def teardown
- Object.instance_eval { remove_const :FooClassWithBarMethod }
- end
- def test_alias_method_chain
- assert @instance.respond_to?(:bar)
- feature_aliases = [:bar_with_baz, :bar_without_baz]
- feature_aliases.each do |method|
- assert !@instance.respond_to?(method)
- end
- assert_equal 'bar', @instance.bar
- FooClassWithBarMethod.class_eval { include BarMethodAliaser }
- feature_aliases.each do |method|
- assert_respond_to @instance, method
- end
- assert_equal 'bar_with_baz', @instance.bar
- assert_equal 'bar', @instance.bar_without_baz
- end
- def test_alias_method_chain_with_punctuation_method
- FooClassWithBarMethod.class_eval do
- def quux!; 'quux' end
- end
- assert !@instance.respond_to?(:quux_with_baz!)
- FooClassWithBarMethod.class_eval do
- include BarMethodAliaser
- alias_method_chain :quux!, :baz
- end
- assert_respond_to @instance, :quux_with_baz!
- assert_equal 'quux_with_baz', @instance.quux!
- assert_equal 'quux', @instance.quux_without_baz!
- end
- def test_alias_method_chain_with_same_names_between_predicates_and_bang_methods
- FooClassWithBarMethod.class_eval do
- def quux!; 'quux!' end
- def quux?; true end
- def quux=(v); 'quux=' end
- end
- assert !@instance.respond_to?(:quux_with_baz!)
- assert !@instance.respond_to?(:quux_with_baz?)
- assert !@instance.respond_to?(:quux_with_baz=)
- FooClassWithBarMethod.class_eval { include BarMethodAliaser }
- assert_respond_to @instance, :quux_with_baz!
- assert_respond_to @instance, :quux_with_baz?
- assert_respond_to @instance, :quux_with_baz=
- FooClassWithBarMethod.alias_method_chain :quux!, :baz
- assert_equal 'quux!_with_baz', @instance.quux!
- assert_equal 'quux!', @instance.quux_without_baz!
- FooClassWithBarMethod.alias_method_chain :quux?, :baz
- assert_equal false, @instance.quux?
- assert_equal true, @instance.quux_without_baz?
- FooClassWithBarMethod.alias_method_chain :quux=, :baz
- assert_equal 'quux=_with_baz', @instance.send(:quux=, 1234)
- assert_equal 'quux=', @instance.send(:quux_without_baz=, 1234)
- end
- def test_alias_method_chain_with_feature_punctuation
- FooClassWithBarMethod.class_eval do
- def quux; 'quux' end
- def quux?; 'quux?' end
- include BarMethodAliaser
- alias_method_chain :quux, :baz!
- end
- assert_nothing_raised do
- assert_equal 'quux_with_baz', @instance.quux_with_baz!
- end
- assert_raise(NameError) do
- FooClassWithBarMethod.alias_method_chain :quux?, :baz!
- end
- end
- def test_alias_method_chain_yields_target_and_punctuation
- args = nil
- FooClassWithBarMethod.class_eval do
- def quux?; end
- include BarMethods
- FooClassWithBarMethod.alias_method_chain :quux?, :baz do |target, punctuation|
- args = [target, punctuation]
- end
- end
- assert_not_nil args
- assert_equal 'quux', args[0]
- assert_equal '?', args[1]
- end
- def test_alias_method_chain_preserves_private_method_status
- FooClassWithBarMethod.class_eval do
- def duck; 'duck' end
- include BarMethodAliaser
- private :duck
- alias_method_chain :duck, :orange
- end
- assert_raise NoMethodError do
- @instance.duck
- end
- assert_equal 'duck_with_orange', @instance.instance_eval { duck }
- assert FooClassWithBarMethod.private_method_defined?(:duck)
- end
- def test_alias_method_chain_preserves_protected_method_status
- FooClassWithBarMethod.class_eval do
- def duck; 'duck' end
- include BarMethodAliaser
- protected :duck
- alias_method_chain :duck, :orange
- end
- assert_raise NoMethodError do
- @instance.duck
- end
- assert_equal 'duck_with_orange', @instance.instance_eval { duck }
- assert FooClassWithBarMethod.protected_method_defined?(:duck)
- end
- def test_alias_method_chain_preserves_public_method_status
- FooClassWithBarMethod.class_eval do
- def duck; 'duck' end
- include BarMethodAliaser
- public :duck
- alias_method_chain :duck, :orange
- end
- assert_equal 'duck_with_orange', @instance.duck
- assert FooClassWithBarMethod.public_method_defined?(:duck)
- end
- def test_delegate_with_case
- event = Event.new(Tester.new)
- assert_equal 1, event.foo
- end
- end