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

Include modules instead of reopening classes. #14151

Merged

Conversation

jrafanie
Copy link
Member

@jrafanie jrafanie commented Mar 2, 2017

Related to #14128

We should either use RssFeed.class_eval to reopen the class to force
rails to load the RssFeed model first or the technique in this commit,
which is to just include the module in RssFeed. Note, this module was
already being included so there was no reason to reopen the class also.

The existing layout of re-opening the RssFeed with different class
definitions:

rss_feed/import_export.rb:
class RssFeed

rss_feed.rb:
class RssFeed < ApplicationRecord

can cause TypeError: superclass mismatch for class RssFeed if
the import_export.rb is loaded first.

@jrafanie jrafanie added the bug label Mar 2, 2017
@jrafanie
Copy link
Member Author

jrafanie commented Mar 2, 2017

@isimluk @lpichler Please review.

@jrafanie jrafanie force-pushed the include_a_module_dont_reopen_class branch from 5de608a to a8ea58b Compare March 2, 2017 22:43
@@ -1,6 +1,7 @@
require 'resource_feeder/common'
class RssFeed < ApplicationRecord
include ResourceFeeder
include_concern 'ImportExport'
Copy link
Contributor

Choose a reason for hiding this comment

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

It is already on line 11

Copy link
Member Author

Choose a reason for hiding this comment

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

OMG, WAT, thanks!

Copy link
Member Author

Choose a reason for hiding this comment

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

Why are we reopening the class if we're already including the module???

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks @lpichler. I guess I didn't even expect that this module was already included... I moved the include with the other include so it's more obvious.

👍

Copy link
Contributor

@lpichler lpichler left a comment

Choose a reason for hiding this comment

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

just one thing I found, see comment

@lpichler
Copy link
Contributor

lpichler commented Mar 3, 2017

@jrafanie @isimluk, as we noticed, for this extending classes we have two patterns in our application as was described, for example taken from this PR:

1. Extending by redefinition of class

class RssFeed
  module ImportExport
    extend ActiveSupport::Concern

2. Extending by module

module RssFeed::ImportExport
  extend ActiveSupport::Concern
  ...

with include_concern in 'main' class

class RssFeed
  include_concern 'ImportExport'

For me is sort of confusing to have statement of class definition on two places but maybe it is ok in ruby.

or should we rather use only 2) ? What do you think ?

Copy link
Member

@isimluk isimluk left a comment

Choose a reason for hiding this comment

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

I don't have a strong opinion over the change. I felt re-open is just fine (ruby is strict and fails early).

except for Libor's comment I am 👍 🍰 🥄

Related to ManageIQ#14128

We should either use RssFeed.class_eval to reopen the class to force
rails to load the RssFeed model first or the technique in this commit,
which is to just include the module in RssFeed.  Note, this module was
already being included so there was no reason to reopen the class also.

The existing layout of re-opening the RssFeed with different class
definitions:

rss_feed/import_export.rb:
class RssFeed

rss_feed.rb:
class RssFeed < ApplicationRecord

can cause `TypeError: superclass mismatch for class RssFeed` if
the import_export.rb is loaded first.
@jrafanie jrafanie force-pushed the include_a_module_dont_reopen_class branch from a8ea58b to 0229960 Compare March 3, 2017 15:20
@miq-bot
Copy link
Member

miq-bot commented Mar 3, 2017

Checked commit jrafanie@0229960 with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0
4 files checked, 1 offense detected

app/models/rss_feed/import_export.rb

@jrafanie
Copy link
Member Author

jrafanie commented Mar 3, 2017

I don't have a strong opinion over the change. I felt re-open is just fine (ruby is strict and fails early).

@isimluk If this is was straight ruby where you require your dependencies and don't rely on rails autoload, I'd totally agree. With rails autoload, if the constant is already defined, rails won't autoload rss_feed.rb if import_export.rb already defined RssFeed constant. I think the only options are RssFeed.class_eval in the extension to force rails to autoload RssFeed model first or use modules like this PR does.

Ok, I made the change recommended by @lpichler and updated the description. Thanks again for the 👀

@jrafanie jrafanie closed this Mar 3, 2017
@jrafanie jrafanie reopened this Mar 3, 2017
@isimluk
Copy link
Member

isimluk commented Mar 7, 2017

With rails autoload, if the constant is already defined, rails won't autoload rss_feed.rb if import_export.rb
already defined RssFeed constant.

I have looked into the rails autoload code last week (in relation with #14128). I haven't found a place/condition where this could happen silently. If the developer makes a mistake (hardoces require), he/she will soon learn about the mistake. (Unless of course, they do not silence_warnings). Hence, I am not terrified by re-open now.

Historical evidence speaks for itself. This problem was never existed, until we introduced coverall-load-all thingy.

So we can get a rid of this pattern (partially). However, I would be much more concerned about the silence_warnings.

@jrafanie
Copy link
Member Author

jrafanie commented Mar 7, 2017

Historical evidence speaks for itself. This problem was never existed, until we introduced coverall-load-all thingy.

@isimluk yeah, this is true for this specific problem. The general problem of autoloading constants in the correct order has hit us many times. Avoiding load order issues by making the base thing include the extending module, what this PR does, and using the RssFeed.class_eval trick are the two ways that seem to get the right behavior. I wish it was easier.

@isimluk isimluk added this to the Sprint 56 Ending Mar 13, 2017 milestone Mar 10, 2017
@isimluk isimluk merged commit 5075263 into ManageIQ:master Mar 10, 2017
@jrafanie jrafanie deleted the include_a_module_dont_reopen_class branch March 10, 2017 13:41
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.

5 participants