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

Fix generators (@dgynn); load Railtie only with Rails, ensures caching configured #1352

Merged
merged 8 commits into from
Jan 19, 2016

Conversation

bf4
Copy link
Member

@bf4 bf4 commented Nov 30, 2015

Fixing the generators (@dgynn)

Only load generators when needed

  • use hook_for to hook in the serializer and remove load_generators
  • move generators so they can be found by rails
  • move to_prepare block to railtie config

This commit improves the way the generators are loaded and how
they extend the resource generator.

  • The initializer block has been changed to a generator block which is only executed when generators are needed.
  • The call to app.load_generators has been removed. There is no need to load all generators.
  • The resource_override.rb has been changed to use hook_for to extend the resource generator.
  • The directory for the generators has been moved to match the way Rails looks to load generators.

With hook_for it would now be possible for a user to pass --no-serializer to skip that option.
The --serialize option also now shows up in the generator help with rails g resource --help.

These changes follow the way the Draper gem extends the controller generator.

Putting Rails Code in the Railties (@bf4)

akak let people use AMS without requiring 'rails' or 'action{pack,view}'

Only call railtie when Rails is defined; assume controller loaded

Isolated Testing

Misc

  • Turns out mattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }
    was always nil until the Railtie was loaded, since mattr_accessor
    block defaults don't really work on modules, but on the classes that
    include them.

  • Should resolve 0.10.0.rc3 outside of rails? #1389 where Railties was being too-eagerly loaded.

  • Commented on importance of Rails being required first for caching to
    work
    . Ref Cache not working #923 (comment)

    +    # To be useful, this hook must run after Rails has initialized,
    +    # BUT before any serializers are loaded.
    +    # Otherwise, the call to 'cache' won't find `cache_store` or `perform_caching`
    +    # defined, and serializer's `_cache_store` will be nil.
    +    # IF the load order cannot be changed, then in each serializer that that defines a `cache`,
    +    # manually specify e.g. `PostSerializer._cache_store = Rails.cache` any time
    +    # before the serializer is used.  (Even though `ActiveModel::Serializer._cache_store` is
    +    # inheritable, we don't want to set it on `ActiveModel::Serializer` directly unless
    +    # we want *every* serializer to be considered cacheable, regardless of specifying
    +    # `cache # some options` in a serializer or not.
    +    initializer 'active_model_serializers.caching' => :after_initialize do
    +      ActiveModelSerializers.config.cache_store     = ActionController::Base.cache_store
    +      ActiveModelSerializers.config.perform_caching = Rails.configuration.action_controller.perform_caching
    +    end
  • In isolated tests, active_support/core_ext/object/with_options is required.

ActiveModel::Serializer.serializers_cache.clear
end
end
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if maybe this shouldn't be in an initializer

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does, however, make it easier to conditionally disable including the module into action controller. e.g. https://github.com/rails-api/active_model_serializers/pull/592/files and #1295 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the include ::ActionController::Serialization in an initializer is good for being able to conditionally disable it based on whatever gets decided from #1295. And having the on_load(:action_controller) is good for lazy-loading in case ActionController::Base is never loaded. Those both seem good.

The to_prepare block does not need to be in the initializer. It could be outside the initializers on the Railtie itself with just...

  config.to_prepare do
    ActiveModel::Serializer.serializers_cache.clear
  end

Using an initializer, and a load hook (:action_controller), and then running another load hook (:active_model_serializers) to set the logger seems like overly complicated. Depending on load ordering, someone could have an initializer that explicitly sets ActiveModelSerializers.logger but then gets overwritten.
Is there any other reason to have the :active_model_serializers lazy-load hook? Could that logic just get folded in where the run_load_hooks call is? Would you ever expect someone else to hook into that? And if so, would it only be after :action_controller has been loaded?

I'm still poking around a bit to see if I've got the order right on some of these.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dgynn awesome! Thanks for looking at this! Feel free to submit a PR into it if you'd like.

Also, see #1353 which is similar to #1295

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dgynn

Using an initializer, and a load hook (:action_controller), and then running another load hook (:active_model_serializers) to set the logger seems like overly complicated. Depending on load ordering, someone could have an initializer that explicitly sets ActiveModelSerializers.logger but then gets overwritten.
Is there any other reason to have the :active_model_serializers lazy-load hook?

Since the logger isn't necessarily derived from the controller, I'm just being paranoid that someone might configure the logger before the controller was loaded. This makes sure the user has the final say.. but I could me misthinking that

@bf4
Copy link
Member Author

bf4 commented Dec 2, 2015

cc @rails-api/ams

@bf4
Copy link
Member Author

bf4 commented Dec 22, 2015

ref: @dgynn has made a PR into the merge source bf4#1

@bf4
Copy link
Member Author

bf4 commented Dec 23, 2015

@dgynn merged in bf4#1

sh(Gem.ruby, '-w', "-I#{dir}/lib", "-I#{dir}/test", file) or fail 'Failures' # rubocop:disable Style/AndOr
end
end
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see commit message, but basically this is adapted from ActiveJob Rakefile

@bf4 bf4 force-pushed the railties branch 2 times, most recently from b63f6ca to a7e16ad Compare December 28, 2015 05:42
- rvm: jruby-9000
env: JRUBY_OPTS='--server -Xcompile.invokedynamic=false -Xcli.debug=true --debug'
- rvm: jruby-9.0.4.0
env: JRUBY_OPTS='-Xcompat.version=2.0 --server -Xcompile.invokedynamic=false -Xcli.debug=true --debug'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change belong here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, from the jruby pr. Had a failute

B mobile phone

On Dec 29, 2015, at 4:15 PM, Lucas Hosseini [email protected] wrote:

In .travis.yml:

@@ -33,8 +33,8 @@ matrix:
include:

  • rvm: 2.2
    env: CAPTURE_STDERR=true
      • rvm: jruby-9000
    • env: JRUBY_OPTS='--server -Xcompile.invokedynamic=false -Xcli.debug=true --debug'
      • rvm: jruby-9.0.4.0
    • env: JRUBY_OPTS='-Xcompat.version=2.0 --server -Xcompile.invokedynamic=false -Xcli.debug=true --debug'
      Does this change belong here?


Reply to this email directly or view it on GitHub.

@beauby
Copy link
Contributor

beauby commented Dec 29, 2015

I'm not familiar enough with railties. Would you mind summarizing what this PR does?

@bf4
Copy link
Member Author

bf4 commented Dec 30, 2015

@beauby Updated the description from the commit messages #1352 (comment). Thanks for the nudge

@bf4 bf4 mentioned this pull request Jan 4, 2016
@bf4 bf4 force-pushed the railties branch 5 times, most recently from de0189c to a2f30a1 Compare January 14, 2016 02:26
end

if ENV['RAILS_VERSION'].to_s > '4.0' && RUBY_ENGINE == 'ruby'
task default: [:isolated, :test, :rubocop]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isolated tests as set up here break on 4.0 and on JRuby

@dgynn
Copy link
Contributor

dgynn commented Jan 14, 2016

I've pushed up a PR to your branch that shows the changes I'd suggest. I did not update all the tests or change the comment about cache setup. Feel free to edit or disregard. :)

BTW, you might be interested in a tool I'm working on that inspects Rails configuration info.
https://github.com/dgynn/tuttle
In particular, it can list out all of the initializers configured for an app and show their order and dependencies. Here is a demo of that with my suggested changes installed. Look at the initializers tab...
https://tuttle-demo.herokuapp.com/tuttle/rails

Working on that is how I came across the generators issue initially.

require 'active_model/serializable_resource'
require 'active_model/serializer/version'
class << self; attr_accessor :logger; end
self.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the mattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) } is more legible than this one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe mattr_accessor does not support blocks in ActiveSupport 4.0.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See pr description. It didn't work

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

bf4 and others added 7 commits January 15, 2016 01:52
- use hook_for to hook in the serializer and remove load_generators
- move generators so they can be found by rails
- move to_prepare block to railtie config

This commit improves the way the generators are loaded and how
they extend the resource generator.

* The initializer block has been changed to a `generator` block which is only executed when generators are needed.
* The call to `app.load_generators` has been removed. There is no need to load *all* generators.
* The `resource_override.rb` has been changed to use `hook_for` to extend the resource generator.
* The directory for the generators has been moved to match the way Rails looks to load generators.

With `hook_for` it would now be possible for a user to pass `--no-serializer` to skip that option.
The `--serialize` option also now shows up in the generator help with `rails g resource --help`.

These changes follow the way the Draper gem extends the `controller` generator.
Isolated Testing

- Rake test inspired by https://github.com/rails/rails/blob/v5.0.0.beta1/activejob/Rakefile
- Isolated unit inspired by
  - https://github.com/rails/rails/blob/v5.0.0.beta1/railties/test/isolation/abstract_unit.rb
  - https://github.com/rails/rails/blob/v5.0.0.beta1/activemodel/test/cases/railtie_test.rb

Misc

- Turns out `mattr_accessor(:logger) {
  ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }`
  was always nil until the Railtie was loaded, since mattr_accessor
  block defaults don't really work on modules, but on the classes that
  include them.
- Commented on important on Rails being required first for caching to
  work.
- In isolated tests, `active_support/core_ext/object/with_options` is required.
this uses the configuration settings rather than calling ActionController::Base to get the configured values.
after the "action_controller.set_configs" initializer has run, the configuration option holds the value Base will get when it loads.
@bf4
Copy link
Member Author

bf4 commented Jan 15, 2016

@maurogeorge @dgynn updated

@maurogeorge
Copy link
Member

LGTM. I only recommend take a look at the @dgynn comments #1352 (comment) #1352 (comment) that worked on this part of the project 👍

@bf4
Copy link
Member Author

bf4 commented Jan 15, 2016

@maurogeorge I merged in his code... but I'm tired.. besides the value in re-reading the comments, was there more work to do that I missed?

@maurogeorge
Copy link
Member

@bf4 no, to me looks good. @dgynn let us know if you have more concerns about this.

@dgynn
Copy link
Contributor

dgynn commented Jan 15, 2016

This looks good. I do think the comment in the Railtie about caching can now be removed but that should be verified.
Also, the 2 initializer blocks for caching and logging could be combined. There really isn't much benefit to having them separate. ActionController itself used to have 2 separate initializers for logging and caching and they combined them here... rails/rails@fbc9d0f

@bf4
Copy link
Member Author

bf4 commented Jan 15, 2016

Can I give you commit to my fork to finish it? I'm on vacation

Re comment there are tests for it

B mobile phone

On Jan 15, 2016, at 12:34 PM, Dave Gynn [email protected] wrote:

This looks good. I do think the comment in the Railtie about caching can now be removed but that should be verified.
Also, the 2 initializer blocks for caching and logging could be combined. There really isn't much benefit to having them separate. ActionController itself used to have 2 separate initializers for logging and caching and they combined them here... rails/rails@fbc9d0f


Reply to this email directly or view it on GitHub.

this also changes the action_controller load hook to not trigger loading of the ActionController::Base
@dgynn
Copy link
Contributor

dgynn commented Jan 16, 2016

I've updated the Railtie to combine the initializers and update the comment. I believe this initializer ordering should resolve the caching issue from #923 and also not trigger too-early loading of ActionController::Base. I'd say this is ready to be merged.

@bf4
Copy link
Member Author

bf4 commented Jan 17, 2016

@dgynn looks good. pr description still good summary?

@@ -0,0 +1,36 @@
require 'rails/railtie'
require 'action_controller'
require 'action_controller/railtie'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still necessary?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AMS railtie does require that the action_controller/railtie has been loaded so that Rails.configuration.action_controller exists. But there isn't any normal that wouldn't have already been required. It should have been loaded by rails/all or even active_record/railtie (see the comment here https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railtie.rb#L5).

@bf4
Copy link
Member Author

bf4 commented Jan 19, 2016

Ok, anything than needs to be resolved before merging this? I'll add an issue with label 'pr followup' for what we've discussed

@dgynn
Copy link
Contributor

dgynn commented Jan 19, 2016

@bf4 This looks good to merge to me.

bf4 added a commit that referenced this pull request Jan 19, 2016
Fix generators (@dgynn); load Railtie only with Rails, ensures caching configured
@bf4 bf4 merged commit 8981683 into rails-api:master Jan 19, 2016
@bf4 bf4 deleted the railties branch January 19, 2016 04:24
@bf4
Copy link
Member Author

bf4 commented Jan 19, 2016

merged. Let the heavens be glad; let the earth rejoice

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

Successfully merging this pull request may close these issues.

0.10.0.rc3 outside of rails?
4 participants