Skip to content

Instantly share code, notes, and snippets.

@gazay
Last active August 29, 2015 14:19
Show Gist options
  • Save gazay/a51dee0bd6bcafb65dfd to your computer and use it in GitHub Desktop.
Save gazay/a51dee0bd6bcafb65dfd to your computer and use it in GitHub Desktop.
Strange behavior of Module#attr_reader
class Module
private
def define_new_attr
attr_reader :new_attr
end
end
A = Class.new
A.send :define_new_attr
puts A.new.methods.include?(:new_attr)

If run this with ruby test.rb with MRI, Jruby, and in MRI irb: true

If run in Jruby irb: false

I think it can be related in following failing rails tests, but I'm not sure:

  3) Error:
AttrInternalTest#test_naming_format:
NoMethodError: private method `foo=' called for #<#<Class:0x64ea9235>:0x6af12899>
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:47:in `block in test_naming_format'
    /Users/alex/code/opensource/rails/activesupport/lib/active_support/test_case.rb:82:in `assert_nothing_raised'
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:47:in `test_naming_format'


  4) Error:
AttrInternalTest#test_reader:
NoMethodError: private method `foo' called for #<#<Class:0x54d4c35f>:0x7db205ba @_foo=1>
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:17:in `block in test_reader'
    /Users/alex/code/opensource/rails/activesupport/lib/active_support/test_case.rb:82:in `assert_nothing_raised'
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:17:in `test_reader'


  5) Error:
AttrInternalTest#test_writer:
NoMethodError: private method `foo=' called for #<#<Class:0x4df95b03>:0x2eaf17c5>
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:24:in `block in test_writer'
    /Users/alex/code/opensource/rails/activesupport/lib/active_support/test_case.rb:82:in `assert_nothing_raised'
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:24:in `test_writer'


  6) Error:
AttrInternalTest#test_accessor:
NoMethodError: private method `foo=' called for #<#<Class:0x5c13e774>:0x31e1a699>
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:34:in `block in test_accessor'
    /Users/alex/code/opensource/rails/activesupport/lib/active_support/test_case.rb:82:in `assert_nothing_raised'
    /Users/alex/code/opensource/rails/activesupport/test/core_ext/module/attr_internal_test.rb:34:in `test_accessor'

The problem appears on this for example line: https://github.com/rails/rails/blob/master/activesupport/test/core_ext/module/attr_internal_test.rb#L14.

Couple of lines before that called method attr_internal which defined here https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/module/attr_internal.rb.

As you can see this method calls private method which sends :attr_reader from private method in module https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/module/attr_internal.rb#L31. In 'normal' behavior of mri and jruby it should lead to defining public attribute reader method but in tests and in jruby irb and when I tried to debug this with ruby-debug – it defines private method. And tests fails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment