Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move SourceAnnotationExtractor under Rails module #32065

Conversation

sikachu
Copy link
Member

@sikachu sikachu commented Feb 20, 2018

This is pretty much just a housekeeping PR.

I was browsing http://edgeapi.rubyonrails.org/ and notices that this class is listed on the left size with no namespace prefix. Given that this class belongs to Rails framework, and that it's already in railties/lib/rails hierarchy, I believe it's best to move this class down into Rails module.

In some sense, I believe that this could be considered a breaking change. However, given that user will access this class through rake task, I think this is fine to change.

Please let me know what you think.

@matthewd
Copy link
Member

https://github.com/search?l=Ruby&q=SourceAnnotationExtractor+-filename%3Aannotations.rake&type=Code seems to show some usage, so I think it's worth a deprecation.

@sikachu
Copy link
Member Author

sikachu commented Feb 20, 2018

@matthewd sounds good. So deprecate the constant in 6.0, then remove it in 6.1?

@matthewd
Copy link
Member

Yup. Rename stays the same; we just add in a http://api.rubyonrails.org/classes/ActiveSupport/Deprecation/DeprecatedConstantProxy.html for the old name.

@sikachu
Copy link
Member Author

sikachu commented Mar 22, 2018

@matthewd sorry for the delay — I just updated the PR with two things:

  • I add deprecation notice for SourceAnnotationExtractor as you suggested.
  • I also moved the Annotation sub-struct into a proper class so RDoc would properly render it in the documentation.

Please let me know if you have any feedback. Thanks!

This class should be under Rails module as it belongs to Rails.
This cleans up the documentation for SourceAnnotationExtractor because
RDoc does not seems to know how to parse `Struct.new() do` block.
1.2.1 fixes a bug in `Kernel.require` and resolve a test failure.

See Shopify/bootsnap#143
@sikachu sikachu force-pushed the move-SourceAnnotationExtractor-under-rails-namespec branch from a252858 to f2ebfcb Compare March 23, 2018 01:10
@sikachu
Copy link
Member Author

sikachu commented Mar 23, 2018

I added a commit to update bootsnap to the latest version to fix the issue with Kernel.require that caused a test failure. This is ready for another look.

@kaspth kaspth merged commit 0ec23ef into rails:master Apr 2, 2018
@kaspth
Copy link
Contributor

kaspth commented Apr 2, 2018

Thanks, @sikachu!

@eugeneius
Copy link
Member

RSpec Rails is broken by this change because it accesses SourceAnnotationExtractor::Annotation directly, and ActiveSupport::Deprecation::DeprecatedConstantProxy can't handle nested constants:

TypeError: Rails::SourceAnnotationExtractor is not a class/module
/Users/eugene/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/rspec-rails-3.7.2/lib/rspec-rails.rb:12:in `<class:Railtie>'
/Users/eugene/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/rspec-rails-3.7.2/lib/rspec-rails.rb:8:in `<module:Rails>'
/Users/eugene/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/rspec-rails-3.7.2/lib/rspec-rails.rb:6:in `<module:RSpec>'
/Users/eugene/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/rspec-rails-3.7.2/lib/rspec-rails.rb:4:in `<top (required)>'

Is there a way we can avoid breaking SourceAnnotationExtractor::Annotation, while still deprecating the top-level SourceAnnotationExtractor constant?

@sikachu sikachu deleted the move-SourceAnnotationExtractor-under-rails-namespec branch April 5, 2018 00:58
@sikachu
Copy link
Member Author

sikachu commented Apr 5, 2018

😦 interesting. I'm sorry for breaking your code.

Let me try to find a way to work around that. I assume that this only happen when rspec-rails is built against Rails master right?

@matthewd
Copy link
Member

matthewd commented Apr 5, 2018

http://api.rubyonrails.org/classes/ActiveSupport/Deprecation/DeprecatedConstantAccessor.html exists for that purpose, but I don't like the idea of using it at the top level 😕

Maybe we can make DeprecatedConstantProxy inherit from Module, and then define both method_missing and const_missing?

@eugeneius
Copy link
Member

I assume that this only happen when rspec-rails is built against Rails master right?

Right 👍 I discovered the problem when testing my application against Rails master, which I'm only doing to try to flush out regressions in Rails. I'm not blocked by it, no apology necessary 🙂

Maybe we can make DeprecatedConstantProxy inherit from Module

This does appear to work! 💥

@sikachu
Copy link
Member Author

sikachu commented Jun 4, 2018

Just want to drop a note that I'm now working on this to make sure that nobody else would run into the same issue as @eugeneius 😅

I'm currently trying to fix rspec-rails test to work against Rails master right now though (needs to update rails-controller-testing gemspec) ... so after that I can proceed with the fix 🙇

rafaelfranca pushed a commit that referenced this pull request Jun 24, 2019
With this code (exctracted from derailed_benchmarks):

```ruby

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  gem "rails", "~> 6.0.0.rc1", require: false
end

FILES = [
  "rails/engine/configuration",
  "rails/source_annotation_extractor",
  "active_support/deprecation"
]

module Kernel
  alias :original_require :require

  def require(file)
    Kernel.require(file)
  end

  class << self
    alias :original_require :require
  end
end

Kernel.define_singleton_method(:require) do |file|
  original_require(file)
end

FILES.each do |file|
  puts "requiring file: #{file}"
  require file
end
```

It fails with Rails 6 and the change introduced by 32065
```
requiring file: rails/engine/configuration
requiring file: rails/source_annotation_extractor
Traceback (most recent call last):
	11: from repro_derailed.rb:33:in `<main>'
	10: from repro_derailed.rb:33:in `each'
	 9: from repro_derailed.rb:35:in `block in <main>'
	 8: from repro_derailed.rb:21:in `require'
	 7: from repro_derailed.rb:30:in `block in <main>'
	 6: from repro_derailed.rb:30:in `require'
	 5: from /Users/benoit.tigeot/.rvm/gems/ruby-2.5.1/gems/railties-6.0.0.rc1/lib/rails/source_annotation_extractor.rb:8:in `<top (required)>'
	 4: from /Users/benoit.tigeot/.rvm/gems/ruby-2.5.1/gems/activesupport-6.0.0.rc1/lib/active_support/deprecation/proxy_wrappers.rb:10:in `new'
	 3: from /Users/benoit.tigeot/.rvm/gems/ruby-2.5.1/gems/activesupport-6.0.0.rc1/lib/active_support/deprecation/proxy_wrappers.rb:10:in `new'
	 2: from /Users/benoit.tigeot/.rvm/gems/ruby-2.5.1/gems/activesupport-6.0.0.rc1/lib/active_support/deprecation/proxy_wrappers.rb:125:in `initialize'
	 1: from /Users/benoit.tigeot/.rvm/gems/ruby-2.5.1/gems/activesupport-6.0.0.rc1/lib/active_support/deprecation/proxy_wrappers.rb:23:in `method_missing'
/Users/benoit.tigeot/.rvm/gems/ruby-2.5.1/gems/activesupport-6.0.0.rc1/lib/active_support/deprecation/proxy_wrappers.rb:148:in `warn': private method `warn' called for nil:NilClass (NoMethodError)
```

Related:
- zombocom/derailed_benchmarks#130
- #32065
sikachu added a commit to sikachu/rails that referenced this pull request Jul 5, 2019
This commit fixes rails#36313.

After rails#32065 moved `SourceAnnotationExtractor` into `Rails` module, it
broke the ability to access `SourceAnnotationExtractor::Annotate`
directly as user would get this error:

    TypeError: Rails::SourceAnnotationExtractor is not a class/module

This commit fixes the issue by making `DeprecatedConstantProxy` to
inherit from `Module` and then defines `method_missing` and
`const_missing` to retain the previous functionality.

Thank you Matthew Draper for the idea of how to fix the issue!

[Prem Sichanugrist & Matthew Draper]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants