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

How to import/export coffeescript Classes between files? #11

Open
uglycoyote opened this issue Sep 13, 2017 · 6 comments
Open

How to import/export coffeescript Classes between files? #11

uglycoyote opened this issue Sep 13, 2017 · 6 comments

Comments

@uglycoyote
Copy link

Pardon me for the vague question-issue here. I'm not quite sure what part of the guanlecoja stack this is related to.

I have a buildbot plugin which was working but it has one rather large source file that I'm trying to break up into several smaller source files. For example i have coffeescript a class called ConsoleUIHelpers which I broke into a separate file. Now I'm getting ReferenceError: ConsoleUIHelpers is not defined

Searching the scripts.js that some part of the guanlecoja framework is outputting I do find my class in the outputted code:

(function() {
  var ConsoleUIHelpers, consoleUIHelpers,
    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  ConsoleUIHelpers = (function() {
  ...
}).call(this);

which appears before the code which is failing with the ReferenceError

It's not clear to me where/why the code is getting surrounded by the (function() { ... }).call(this) , but that seems to be what is preventing the subsequent code from having ConsoleUIHelpers as an identifier that it can access.

When I pass my class through a regular-old coffeescript-to-js conversion it does not surround it with (function() { ... }).call(this), so I'm guessing that it is coming from some other part of the guanlecoja framework, but i have no idea which piece of technology does this.

from reading https://stackoverflow.com/questions/2421911/what-is-the-purpose-of-wrapping-whole-javascript-files-in-anonymous-functions-li, I'm assuming that surrounding the code with (function() { ... }).call(this) is some kind of namespacing mechanism, though the examples in that stack overflow do something like var myPlugin = (function() { ... }).call(this) which then gives an identifier with which to access the contents of the namespace.

Apologies for my ignorance, I don't even know what to research in this case since reading about "coffeescript exports", "coffeescript modules" etc. turned up nothing that seemed relevant. I'm familiar with require.js but it doesn't appear to be being used anywhere in buildbot's front-end code, and can't find any examples of any sort of require/import statement to go off.

@tardyp
Copy link
Member

tardyp commented Sep 14, 2017

Hi,

Guanlecoja is a build system designed for AngularJS. AngularJs does provide component reusability through services (and other components). You should create an angular service (optionally via ng-classify) in any file, and use it via dependency injection anywhere.

Problem with defining classes by yourself is that you would have to worry about parsing order of files. Your classes need to be defined before the classes that are using them. Angularjs takes care of all of the via dependency injection.

@uglycoyote
Copy link
Author

Sounds good, I'll make the shared code code a service then! Thanks!

@uglycoyote
Copy link
Author

After exploring this route, refactoring common code into a service seems like it would not always be the appropriate way to solve the problem, since Services appear to impose some additional constraints that may be undesired.

  1. Services are singletons. (according to https://docs.angularjs.org/guide/services). You may not want your refactored class to be a singleton, you may want to create multiple instances of it, e.g. so that they can hold different state or so you can pass in different configuration options to each instance of the refactored class.
  2. Converting code into a service seems to change the lifespan of that object. E.g., if I have a class that used to be instantiated when the controller is created and I turn that class into a service, then it exists before the Controller and is reused if other controllers are created (e.g. you leave the page and come back again)

My conclusion is that while factoring common code into a Service may be the right way to go sometimes, it is not always the correct decision. So I would like to reopen my question about whether guanlecoja provides some means where you can import a class defined in file A into a class defined in file B?

@uglycoyote uglycoyote reopened this Oct 24, 2017
@tardyp
Copy link
Member

tardyp commented Oct 26, 2017

I think you will need to use the factory design pattern in that case.

class Tool
     method1: => return 'foo'

class UtilFactory extends Service
      newTool: -> return new Tool()

then in your other components:

myController = (UtilFactoryService) ->  # angularjs injected function
     tool = UtilFactoryService.newTool()

Again, this is more an angularjs problem than a guanlecoja issue, you should look there on StackOverflow

@uglycoyote
Copy link
Author

My question is really a question about bundling, not about Angular, unless Angular is what's actually doing the bundling, but as far as I can tell it is not. Is Angular what's actually producing the scripts.js in the guanlecoja build system? As far as I can tell from my internet research, bundling is not a problem that Angular tries to solve, instead people tack on additional systems (e.g. webpack, browserify, perhaps gulp) to do the bundling.

What is doing the bundling in guanlecoja?

@tardyp
Copy link
Member

tardyp commented Nov 4, 2017

guanlecoja uses gulp-concat for bundling. That is the very simplest bundler that exists.
guanlecoja only manage order of the bower dependencies, which is the order that is declared in config.coffee.

For the order of the app's files, there is no particular order defined.

Angular does not manage bundling, but it manage dependencies, via dependency injection. So if an app is pure angularjs, there is no need for complex bundling system, you just need to load all the JS, and angular bootstrap system will work.

You can see this article for a longer comparaison of bundler, and how angularjs solve the dependency ordering problem
https://medium.com/@jdxcode/best-practices-for-building-angular-js-apps-266c1a4a6917

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

No branches or pull requests

2 participants