question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Reopens within Engines

See original GitHub issue

Currently, there’s no clear path around the use of reopen or reopenClass that originates from an Engine. As it stands, one can implement an initializer inside an Engine that performs a reopen, and the effect of that initializer can be the modification of globals.

Furthermore, if Engines are loaded lazily, we get into further problems where instances have already been created from classes that are ultimately reopened when an engine loads. At that point, the behavior of the app will be unknown. Additionally, modifying globals at some future point but maybe not at all seems like it’s behavior we don’t want.

One concrete example of the need to reopen is modifying link-to. We currently need to reopen this component to enable data attribute bindings. Reopening is preferable to extending as we want to, as best as possible, retain the ability to use well-known, public components rather than require that our Engineers use custom components.

One possibility that our team has discussed is having an explicit root level initializer that runs all reopens. This will ensure that we have all modifications to global state in one place, that they run at a point-in-time that’s relatively predictable, and that they’re remove the potential for child engines either modifying global state themselves, or overwriting another engine’s modification of global state.

This initializer could look like this:

// global-reopens-initializer.js

import Ember from 'ember';

// import specific reopen functionality
import LinkToReopen from 'global-reopens/link-to-reopen';

function initialize() {
  LinkToReopen.patch();
}

...
// global-reopens/link-to-reopen.js
import Ember from 'ember';

const { LinkComponent } = Ember;

export default {
  patch() {
     LinkComponent.reopen({
      // do reopen stuff here
    });
  }
}

Thoughts on this approach?

Issue Analytics

  • State:open
  • Created 7 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
jbailey4commented, Feb 21, 2018

Looks like this issue/discussion is still opened, so I thought I would add an use-case I found within our app at Ally, that had an unexpected outcome.

We have a large, legacy section of our codebase that I am refactoring to an engine. The consuming app has a global mechanism to track metrics by reopening Ember.ActionHandler#send, so throughout the app a component can simply call this.send('trackSomeCustomEvent'). The legacy section being converted to an engine, unfortunately, has an older metrics implementation that also reopens Ember.ActionHandler#send:

// consuming-app/initializers/metrics.js
...

  Ember.ActionHandler.reopen({
    metrics: service(),
    send(actionName) {
      // track action
    }
  });

...
// engine/initializers/legacy-metrics.js
...

  Ember.ActionHandler.reopen({
    send(actionName) {
      // legacy metrics tracking
    }
  });

...

What I found was both initializers ran and reopened the ActionHandler as expected with no errors, but in the engine when tracking events (i.e. this.send('trackSomeEvent')), ONLY the consuming apps send was ran. Eventually an error would be thrown stating nothing handled the action. I thought at least both send methods would run in the reverse order they were added (as long as calling super()).

This is mostly tech debt within our app and obviously something you would not want to do, but thought I would share as it illustrates some usage/need to reopen the same class within the same application cross engines.

1reaction
nathanhammondcommented, Sep 28, 2016

As a “doctor, it hurts when I do this” “then stop doing it!” fix I would propose that we lock the objects after initializers have been run. This means that anything lazy-loaded or inside of a component can’t blow us up. This would make it much safer, but I don’t know if it actually is compatible with the Ember ecosystem.

Something like #freeze could be interesting too.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Fire Department reopening four engine companies - Phila.gov
The PFD is reopening four engine companies that have been closed for nearly 11 years, restoring critical fire and EMS service in the...
Read more >
Reopen models and controllers from Engine in Rails 3.x app
I want to extend the models and controllers from Engine by reopening them in the Rails app. The problem is they are not...
Read more >
NHTSA reopens investigation into Hyundai, Kia engine fires
The National Highway Traffic Safety Administration is once again investigating a number of Hyundai and Kia vehicles over potential engine fires.
Read more >
DC's Historic Engine 23 Reopens After Renovation
The D.C. fire department celebrated the reopening of one of the oldest fire houses in the District.
Read more >
Ruag Upgrades, Reopens Engine Shop in Stans
Following a four-month upgrade, Ruag Aviation's engine shop in Stans, Switzerland has reopened. Part of a larger push toward efficiency at ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found