# api.modifyClass sometimes(!) not working

**URL:** https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413
**Category:** Bug
**Created:** [December 17, 2021, 7:54am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413 "2021-12-17T07:54:25Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [December 17, 2021, 7:54am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/1 "2021-12-17T07:54:25Z")

</div>

Edit: reclassified as bug.  
Full repro [below](https://meta.discourse.org/t/help-needed-api-modifyclass-sometimes-not-working/212413/12).

I’m using `api.modifyClass` in a theme component.

On most pages this is working fine, but in some topics the property is not added to the user model when the page is reloaded. I cannot find why it is working on most topics, but not working on some, or what the topics where it is not working have in common.

~~Does anyone understand what I am doing wrong here?~~

TL;DR Adding `api.container.lookup` for the model, below the modifyClass, works around this issue.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [December 17, 2021, 9:49am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/2 "2021-12-17T09:49:34Z")

</div>

Oh my word. I might know!

I think that you need to add a `pluginId`

```plaintext
     <script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'my-plugin', 
      testProperty: function() {
        return 1;
      } 
    });
</script>

```

It’s required on later versions, I actually submitted PRs for a couple themes yesterday to add this. I might be turning into a plugin/theme developer at long last

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [December 17, 2021, 11:06am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/3 "2021-12-17T11:06:39Z")

</div>

Thank you Jay! That actually made a difference on my test instance.  
But unfortunately it is not a fix-all golden bullet, the problem is still there :frowning:

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [December 17, 2021, 11:14am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/4 "2021-12-17T11:14:06Z")

</div>

Yeah the `pluginId` is there to prevent modifications being applied twice, I believe. Lack of it should not explain why it hasn’t run once?

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [December 17, 2021, 11:21am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/5 "2021-12-17T11:21:18Z")

</div>

Darn. Just when I thought I knew something. :crying_cat_face:

I thought perhaps if something else was modifying the class then it might be a race condition to see which one did it. But javascript is still mostly a mystery to me.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [December 17, 2021, 11:23am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/6 "2021-12-17T11:23:32Z")

</div>

It’s still an issue with the code, so reasonable to bring up.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [December 17, 2021, 11:30am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/7 "2021-12-17T11:30:09Z")

</div>

> [@pfaffman](#):
>
> race condition

Yes, that crossed my mind as well. But this still fails on a test site with this as the only theme component.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [December 17, 2021, 11:34am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/8 "2021-12-17T11:34:09Z")

</div>

Out of interest, if you add this into a Theme Component in say:

- `/javascripts/discourse/initializers/test-init.js.es6`

instead, does the behaviour change/improve?

I’m not sure if these things are semantically identical …

… theoretically both should be evaluated when the browser refreshes, after which point a race condition should be moot on route transition as the modification should already have been applied …

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [December 17, 2021, 12:15pm UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/9 "2021-12-17T12:15:29Z")

</div>

> [@merefield](#):
>
> does the behaviour change/improve

Nope, same behavior.

I made a theme component with `javascripts/discourse-test/initializers/initialize-discourse-test.js.es6`:

```ruby
import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: 'discourse-test-initializer',
  initialize(){
    console.log('here1');
    withPluginApi("0.1", api => {
      console.log('here2');

      api.modifyClass('model:user', {
        pluginId: 'test',
        testFunction: function() {
          console.log('here3');
          return 2;
        }
      });

    });
  }
}

```

Prints

```plaintext
here1
here2

```

on every page.

On some topics entering `Discourse.currentUser.testFunction()` in the console works and yields `here3` and `2` as output.

On some topics it does not (`Uncaught TypeError: Discourse.currentUser.testFunction is not a function`)

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [December 18, 2021, 9:20am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/11 "2021-12-18T09:20:01Z")

</div>

Ok, I saw a notification from a helpful post that apparently has been removed in the meanwhile.  
The suggestion did not work but it did contain a clue that helped me resolve this.

Adding the following snippet **below the non-working code** consistently resolved the issues I was having. I have tested this on multiple independent forums, both on stable and on tests-passed. I think this should be reclassified as #Contribute > Bug …

```plaintext
<script type="text/discourse-plugin" version="0.1">
const userModel = api.container.lookup("model:user");
</script>

```

@Johani thank you for your help!

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [December 20, 2021, 5:54pm UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/12 "2021-12-20T17:54:20Z")

</div>

Reclassifying this as bug.

I have added a `console.log` in the plugin API code `app/assets/javascripts/discourse/app/lib/plugin-api.js` so it logs whenever `modifyClass` is being called.

I have removed all external plugins to make sure there was not a conflict somewhere.

Repro:

- create an empty forum on `stable` (so no Ember CLI). This is not working on tests-passed (without Ember CLI) either. I did not test this with Ember CLI.

- add a theme component with this in Common - Head

### #1 Working

```plaintext
<script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      } 
    });
</script>

```

- load the home page

- console shows `modifyClass called for model:user _application-08d9058ddd37ba80992f770509f4919ad0738a17f14fb85167b1dc1f32f8b56e.js:23490:16 Object { pluginId: "test-tc", testFunction: testFunction() }`

- enter `Discourse.currentUser.testFunction()` in console

- “1” is printed

### #2 Failing

- Go to a topic, for instance ‘Welcome to Discourse’ and reload the page
- console shows the same “modifyClass called” logs
- enter `Discourse.currentUser.testFunction()` in console
- `Uncaught TypeError: Discourse.currentUser.testFunction is not a function` is printed

### #3 Failing with warning

- Append a single line to top of the theme component so it looks like this:

```plaintext
<script type="text/discourse-plugin" version="0.1">
    const userModel = api.container.lookup("model:user");

    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      } 
    });

</script>

```

- Go to a topic, for instance ‘Welcome to Discourse’ and reload the page
- console shows the same “modifyClass called” logs
- console shows a warning `"model:user" was already cached in the container. Changes won't be applied.`
- enter `Discourse.currentUser.testFunction()` in console
- `Uncaught TypeError: Discourse.currentUser.testFunction is not a function` is printed

### #4 Working

- Move the lookup line to **bottom** of the theme component so it looks like this:

```plaintext
<script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      } 
    });

    const userModel = api.container.lookup("model:user");
</script>

```

- Go to a topic, for instance ‘Welcome to Discourse’ and reload the page
- console shows the same “modifyClass called” logs
- enter `Discourse.currentUser.testFunction()` in console
- “1” is printed :partying_face:

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [June 23, 2022, 9:32am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/13 "2022-06-23T09:32:19Z")

</div>

Revisiting this:

On Discourse 2.8 and up, using `Discourse.User.current().testFunction() `, case #2 is still failing.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [January 15, 2023, 5:04pm UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/16 "2023-01-15T17:04:02Z")

</div>

I’m having an issue with modifyClass too, not sure if it is related?: [Issues overriding getters in a controller (3.0.0)](https://meta.discourse.org/t/issues-overriding-getters-in-a-controller/251793)

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [April 18, 2023, 10:39am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/18 "2023-04-18T10:39:17Z")

</div>

I’ve just improved our warning for this kind of situation:

[https://github.com/discourse/discourse/pull/21140](https://github.com/discourse/discourse/pull/21140)

and also written up this documentation which explains the cause and how to resolve it:

> [@Using modifyClass to change core behavior](https://meta.discourse.org/t/using-modifyclass-for-objects-which-are-initialized-early-in-boot/262064):
>
> For advanced themes and plugins, Discourse offers the modifyClass system. This allows you to extend and override functionality in many of core’s javascript classes. When to use modifyClass modifyClass should be a last resort, when your customization cannot be made via Discourse’s more stable customization APIs (e.g. plugin-api methods, plugin outlets, transformers). Core’s code can change at any time. And therefore, customizations made via modifyClass could break at any time. When using this A…

I think that should take care of all the concerns in this topic. If not, please share some example failing code and I’ll take a look.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [April 22, 2023, 7:00am UTC](https://meta.discourse.org/t/api-modifyclass-sometimes-not-working/212413/19 "2023-04-22T07:00:18Z")

</div>

This topic was automatically closed after 3 days. New replies are no longer allowed.
