Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I declare a variable in a specific scope in coffeescript?

I'm trying to write a jasmine test in coffeescript that uses a beforeEach block. This runs into a problem with coffeescript's variable scoping. Here's what I'd like to write:

describe 'PhoneDetailCtrl', () ->   beforeEach () ->     scope = angular.scope()     $browser = scope.$service('$browser')    it 'should fetch phone detail', () ->     scope.params = {phoneId:'xyz'}     $browser.xhr.expectGET('phones/xyz.json').respond({name:'phone xyz'})     ctrl = scope.$new(PhoneDetailCtrl)      expect(ctrl.phone).toEqualData({})     $browser.xhr.flush()      expect(ctrl.phone).toEqualData({name:'phone xyz'}) 

This doesn't work, though, because the scope and $browser will get declared with var in the innermost scope. That is, once in the beforeEach and then again in the it block. I can force the variables to be declared in the right scope by initializing them, but this seems very strange:

describe 'PhoneDetailCtrl', () ->   $browser = {}   scope = {}   beforeEach () ->     scope = angular.scope()     $browser = scope.$service('$browser')    it 'should fetch phone detail', () ->     scope.params = {phoneId:'xyz'}     ... 

This works, but the javascript it compiles to is actually

describe('PhoneListCtrl', function() {   var $browser, ctrl, scope;   $browser = {};   ctrl = {};   scope = {}; 

where all I need is the line var $browser, ctrl, scope;. Can I write this more concisely in coffeescript?

like image 765
Kevin Peterson Avatar asked Nov 04 '11 06:11

Kevin Peterson


People also ask

How do I declare a variable in CoffeeScript?

In JavaScript, before using a variable, we need to declare and initialize it (assign value). Unlike JavaScript, while creating a variable in CoffeeScript, there is no need to declare it using the var keyword. We simply create a variable just by assigning a value to a literal as shown below.

Which is correct way to declare variable in?

To declare (create) a variable, you will specify the type, leave at least one space, then the name for the variable and end the line with a semicolon ( ; ). Java uses the keyword int for integer, double for a floating point number (a double precision number), and boolean for a Boolean value (true or false).

What keyword is used to define a variable with restricted scope?

Description. let allows you to declare variables that are limited to the scope of a block statement, or expression on which it is used, unlike the var keyword, which declares a variable globally, or locally to an entire function regardless of block scope.

Can I declare the same variable name to the variables which have different scopes in C?

Do not use the same variable name in two scopes where one scope is contained in another. For example, No other variable should share the name of a global variable if the other variable is in a subscope of the global variable.


2 Answers

You are doing it the right way.

This is described in the CoffeeScript documentation. I wouldn't worry about the JS that it creates. Yes, it is a bit messy if you were to write it yourself, but this is one of the things that you have to live with when you use a re-writer like CoffeeScript.

You do, however, have a couple of options which are pretty nice.

You can put the variables in the current context if you wish (which happens to be your jasmine.Spec object for the curious, so it is a relatively safe and appropriate place to be putting variables... just don't overwrite existing vars in the context.):

describe 'PhoneDetailCtrl', () ->   beforeEach () ->     @scope = angular.scope()     @$browser = @scope.$service('$browser')  it 'should fetch phone detail', () ->   @scope.params = {phoneId:'xyz'}   #... etc 

You can also setup your own variable in which to store things

describe 'PhoneDetailCtrl', () ->   setup = {}    beforeEach () ->     setup.scope = angular.scope()     setup.$browser = setup.scope.$service('$browser')    it 'should fetch phone detail', () ->     setup.scope.params = {phoneId:'xyz'}     #... etc 
like image 158
Brian Genisio Avatar answered Sep 16 '22 17:09

Brian Genisio


Your test could be written like the following:

describe "MyGame", ->     mygame = null     beforeEach inject (_MyGame_) ->         mygame = _MyGame_      it "should have two players", ->         expect(mygame.opponents.length).toEqual 2 

Much cleaner syntax - without the need to make things global.

like image 42
Felix Tjandrawibawa Avatar answered Sep 19 '22 17:09

Felix Tjandrawibawa