Question

I am looking at this coffeescript code from Gitlab and wondering how it works.

class Issue
  constructor: ->
    $('.edit-issue.inline-update input[type="submit"]').hide()
    $(".issue-box .inline-update").on "change", "select", ->
      $(this).submit()
    $(".issue-box .inline-update").on "change", "#issue_assignee_id", ->
      $(this).submit()

@Issue = Issue

It seems that this is only being used in the issue related views, but it is not being called anywhere in the issues html. Is there something magical going on behind the scenes here? Also what is the significance of the @Issue = Issue line?

Was it helpful?

Solution

@Issue = Issue simply publishes a local variable to the global scope. This has got nothing to with ruby or rails. It's purely a coffee script idiom.

CoffeeScript executes inside a wrapper which is designed to prevent creating variables in the global scope. And in this wrapper, this (or @) is the global object.

So this:

class Issue
  constructor: ->

@Issue = Issue;

Compiles approximately to this JS:

(function() {
  var Issue;

  Issue = (function() {
    function Issue() {}
    return Issue;
  })();

  this.Issue = Issue;
}.call(window));

In that JS, window becomes this, and properties of window become global variables. So from now on, you only need to type Issue in any other JS file and you will have the issue constructor.

Without the @Issue = Issue line, the Issue constructor would never be available outside that code, and no other file could use it.


In other words, it's the same as this:

window.Issue = Issue;

Which I actually prefer most of the time. It's more clear what's going on as window always means window, but @ can mean many things depending on where it appears.

OTHER TIPS

Just like in JavaScript, there is no proper namespacing in coffeescript. @Issue = Issue translates to this.Issue = Issue. My guess is that this snippet is meant to be concatenated with other files during build, one of them opening an anonymous closure, similar to the one below.

var namespace1 = {subnamespace1: {}};

(function() {
  // Several concatenated files
}).call(namespace1.subnamespace1);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top