#coffee-script
Explore tagged Tumblr posts
Text
Dependency Injection with Node.js
I am currently doing test driven development for a project with Node.js. When I was testing a User 'class' that supposes to communicate with a Mongo database, I thought, what if, what if I would not choose Mongo, but another database instead, or, what if I could not get a database at the moment.
I decided to test with a mock repository instead, using some kind of dependency injection. I use Mocha as my test runner and use Chai.js for assertion.
At first, I have a user-tests.coffee that I write test cases for. My UserMemory.coffee acts as an in-memory repository that will implement register and login methods. These methods interact with an array and push or query from that array.
User = require('../libs/UserMemory').User describe "User Repo", -> userRepo = null beforeEach (done) -> userRepo = new User() done() describe "when registering a new user", -> ### test cases here ###
All the tests passed. Now I want to test User with MongoDB. I could have created the same tests and put into a user-mongo-tests.coffee with a UserMongo.coffee. But then we have duplicate codes every where. Smelly!
So, I extracted the tests into a file shared-user-tests.coffee as below:
should = require("chai").should() exports.shouldBehaveLikeAUserRepo = -> describe "when registering a new user", -> ### Test cases here ###
The user-tests.coffee now only has very little code:
UserMemory = require('../libs/UserMemory').User shared_tests = require('./shared-user-tests') describe 'User Memory Repo', -> beforeEach (done) -> @userRepo = new UserMemory() done() shared_tests.shouldBehaveLikeAUserRepo()
Note the @ in front of userRepo? This is a cool feature of Mocha that allows you to store the context in all test cases. You just have to put @ in front of userRepo in all the shared test cases.
Writing a user-mongo-tests.coffee is now pretty simple:
UserMongo = require('../libs/UserMongo').User Mongo = require("../libs/Mongo").Mongo shared_tests = require('./shared-user-tests') describe 'User Mongo Repo', -> dbInfo = name: 'test' url: 'localhost' port: 10015 mongo = new Mongo(dbInfo) before (done) -> mongo.connect => @userRepo = new UserMongo {repo: mongo} done() beforeEach (done) -> users = mongo.getCollection 'users' users.remove -> #clear the database done() shared_tests.shouldBehaveLikeAUserRepo()
libs/Mongo module is a custom written adapter to talk with MongoDB.
Note: Your UserMongo.coffee should be written to query directly to MongoDB instead of in-memory array like UserMemory.coffee
3 notes
·
View notes
Text
Backbone and jquery details
el --> All views have a DOM element at all times (the el property)
e.preventDefault() -> Its for preventing the default action on a particular event
e.stopPropagation() -> prevents the event from parent dom manipulations
3 notes
·
View notes
Text
Seed Repo: Angular, Bootstrap, Coffee-Script, D3, Express, Grunt, Karma, Node, Stylus!
I was working on a larger personal project and decided to share my work, it is available on github. Grunt automates the tasks of compiling, watching, running the server. It integrates with LiveReload and uses Karma for unit and end-to-end tests which are also automated using grunt.
Original Repo Readme
I just found an awesome tutorial on Grunt for anyone interested.
Summary
I created this project because I wanted to use Angular with Coffee-Script and Bootstrap and I could not find a good seed project. I structured the directory in such a way that all files requiring compiling are stored in /src. Grunt is included to automate a lot of the tasks such as compiling. I also included an Express server that servers the static files from /app on http://localhost:4000.
This project combines into a prebuilt package:
Angular - MVW - lets you write client-side web applications as if you had a smarter browser.
Bootstrap - Sleek, intuitive, and powerful front-end framework for faster and easier web development.
Coffee-Script - a little language that compiles into JavaScript.
D3 - a JavaScript library for manipulating documents based on data.
Express - a minimal and flexible node.js web application framework.
Grunt - The JavaScript Task Runner
Karma - Spectacular Test Runner for JavaScript
Node - a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications.
Stylus - Expressive, dynamic, robust CSS
Quick Start
This will compile all required files to view the basic app page (from the angular seed project) and start a web server to view the app. If you run into problems visit the section about globally required node packages.
git clone https://github.com/EpiphanyMachine/seed.git
install global node dependencies npm install -g <package> for each: grunt-cli coffee-script karma stylus
cd seed
npm install - this will install all local dependencies as listed package.json file
grunt - this will run the default grunt task (compile, start server, watch for changes)
Navigate to http://localhost:4000 and if using livereload activate the extension
DO NOT EDIT ANY .JS or .CSS FILES!
These files should be written in Coffee-Script or Stylus.
All coffee and stylus files are stored in the /src folder. Grunt will compile these for you!
Included Libraries and Frameworks
Client
All packages have been minified, bootstrap is in .css not .less format.
Angular v1.0.7 from the Angular Seed Project
Bootstrap v2.3.2 ported into Bootstrap-Stylus
D3 v3
Node
Included Local Packages
To install the local packages run npm install in seed directory after cloning.
Express v~3.3.4
Grunt v~0.4.1
grunt-contrib-coffee v~0.7.0
grunt-contrib-stylus v~0.6.0
grunt-contrib-watch v~0.5.1
grunt-karma v~0.4.5
grunt-concurrent v~0.3.0
grunt-nodemon v~0.0.8
grunt-exec v~0.4.2
Required Global Node Packages (not included)
Coffee-Script
Grunt-CLI
Karma
Stylus
These can be installed globally using:
npm install -g [package]
How to auto compile live reload changes
See the browser extension how-to here Shortcuts Chrome Firefox
From the /seed directory run grunt this starts the default task (compile, start server, watch for changes)
Karma Overview
Karma can run unit and end-to-end tests. Please check out the information available on their site.
App code testing is done with Karma's unit tests. You will find multiple files in the testing directory related Angular here: seed/test/unit/*.
End-to-end (e2e) testing can also be done by Karma to test front end interactions with your application. You will find this testing file located in seed/test/e2e/scenarios.js
Both of these tests can be run automatically using grunt, see the section below for more information.
How to run karma tests
From the /seed directory run grunt test this starts the test task (compile, start test server, run karma once)
The included web servers
These are automatically started by grunt when needed, you do not need to manually run either of these servers.
The seed/scripts/web-server.js serves the seed directory which includes files required for testing. It can be accessed from http://localhost:8000.
The included express server seed/server.js only servers the seed/app which can be used to serve the application. It can be access from http://localhost:4000.
0 notes
Text
Adding Multiple AngularJS Modules in a single ng-app
Suppose You want to add two AngularJS Modules for your controller.
Say the modules you want are ngSanitize and ngResource.
The documentation/guide available were not clear on the way to do it. Here are some of the resources for your reference:
http://stackoverflow.com/questions/12860595/how-to-define-two-angular-apps-modules-in-one-page
https://groups.google.com/forum/#!msg/angular/lhbrIG5aBX4/4hYnzq2eGZwJ
http://docs.angularjs.org/api/angular.bootstrap
http://docs.angularjs.org/guide/bootstrap
http://docs.angularjs.org/api/angular.module
http://docs.angularjs.org/api/angular.Module#config
http://docs.angularjs.org/guide/module ← [The most useful one]
Following is the way I added two modules (ngSanitize & ngResource) to the same ng-app :
angular.module('app.sanitize', ['ngSanitize']) angular.module('app.resource', ['ngResource']) @app = angular.module("app", ['app.sanitize', 'app.resource']) @MyAppCtrl = ($scope, $resource) -> # Your code goes here # Sample code Blogs = $resource("/blogs/:id", {id: "@id"}, {update: {method: "PUT"}}) $scope.blogs = Blogs.query()
0 notes
Text
Writing your own Canvas Scene Graph
Writing a scene-*what*? The HTML5 Canvas api provides primitive methods to express shapes, strokes and fills, which is all fine and dandy, but in a lot of situations we tend to think of drawing as composed of objects. E.g. to draw what I see from my window I need to draw a tree, a house and some grass, not a sequence of paths. This is true even more when we start animating, typically objects that are part of another object move when the parent object moves. One way to abstract this is to have a graph of objects where some objects are contained in other objects and each object takes care of drawing itself. This is called scene graph rendering. In this article I will show how to build your very own scene graph renderer for the HTML5 canvas. If you are simply looking for a full-featured, pre-built solution, I recommend checking out [CAAT](http://labs.hyperandroid.com/static/caat/). But sometimes you need something easily customizable/lightweight. We will build a single CoffeeScript class that implements everything necessary. ## The basics The first thing that any computer graphics program has to deal with are coordinate systems. We want each object to have it's own independent coordinate system and itself be defined in terms of it's parents. In general this indepence is one of the best reasons for using a scene-graph solution, since canvas tends to have a lot of global state, and you might often face the situation that changing one part of your composition affects a very different part. We wish to avoid that. The simplest way to solve this is to have each object be it's own canvas. So let's start coding: class Entity width: 0 height: 0 constructor: (@width, @height) -> # Create the canvas we will be rendering the object to @canvas = document.createElement('canvas') @canvas.width = @width @canvas.height = @height # Call this function to render out the object, returns a Canvas instance render: -> ctx = @canvas.getContext('2d') # Clear the canvas, important for animation ctx.clearRect(0, 0, @width, @height) @draw(ctx) @canvas # return the canvas # This function should be overriden in subclasses draw: (ctx) -> Now each subclass has to only implement the `draw` method with it's own set of drawing primitives. ## Composition We hover are still not a graph, there is no way in which objects can have no children. First we need to add a few more properties to our class: x: 0 y: 0 children: [] parent: null `x` and `y` are numbers that determine where will the object be drawn in the `parent`'s coordinate system. Let's implement a default `draw` method, that will render the children: draw: (ctx) -> for child in @children ctx.drawImage(child.render(), child.x, child.y) false # return some value, otherwise CoffeeScript will return an array The `drawImage` method takes an Image, Canvas or Video object and draws it at specified coordinates. Since `render` returns a canvas instance with the object drawn in it, we can now render it in the parent canvas. A simple demo of this class:
## Rotations To make this even more worth it, we would like to support rotating any object and having all it's children be rotated as well. Again we need to add a rotation attribute: rotation: 0 and tweak our `draw` function: draw: (ctx) -> for child in @children if child.rotation isnt 0 ctx.save() ctx.translate(child.x, child.y) ctx.rotate(child.rotation) ctx.drawImage(child.render(), 0, 0) ctx.restore() else ctx.drawImage(child.render(), child.x, child.y) false Canvas provides us with all the magic we need. We `save` the current context, then shift our origin point to the child's coordinates (NB: we are going to be rotating children around their origin point, perhaps you would like to implement rotation around center point). Then we do the rotation and drawing and then we simply restore our context to it's original point of origin. ## Shaping up the API First of all since most entity objects will want to override draw in one way or another we might simply use a [Kestrel](https://github.com/raganwald/homoiconic/blob/master/2008-10-29/kestrel.markdown) in the constructor and allow the user to optionally provide it when initiating the class: constructor: (@width, @height, @draw = @draw) -> @canvas = document.createElement('canvas') @canvas.width = @width @canvas.height = @height The `@draw = @draw` might look a bit awkward at first glance, but it assigns as a default our own implementation of `draw` if the user hasn't provided one. The js looks like this: function(draw) { this.draw = (draw != null ? draw : this.draw); } Next let's have a single function for instantiating new Entities and simultaneously adding them as children: add_child: (width, height, draw) -> child = new Entity width, height, draw @children.push child child.parent = @ child # return `child` so that we can do stuff like `collection = scene.add_child 30, 30` You might want to create another class that wraps up some common functionality as creating the top level `Entity` (typically called `Scene`) and setting its canvas as the one actually displayed in the document and setting up animation loops and so on. I'll leave that as an exercise for the reader (hint: look at the fiddles, there you have the basics). ## Caching If you draw expensive things in your objects (and some things in canvas are pretty expensive like shapes with multiple gradients/shadows), you might not want to redraw them 60 times per second. Our architecture allows us to prevent that rather easily. Again we add two more attributes: # This is what the user sets perform_caching: no # This tracks whether or not we should render is_cached: no Now let's modify our `render` function: render: -> return @canvas if @perform_caching and @is_cached ctx = @canvas.getContext('2d') ctx.clearRect(0,0,@width, @height) @draw(ctx) @is_cached = true @canvas We skip all the work when caching is enabled, since the canvas still contains all that was drawn into it. ## Wrapping up And that's basically all there is to it. There are a myriad of features you can add like more transformations apart from rotations, primitive entity subclasses (think something like `Sprite` entity), etc. The complete class is here:
0 notes
Text
Node + CoffeeScript on Windows
With the newest version of Node.js, v0.6.6, now Windows users can start developing their favorite app(s) in Node.js too.
Download the Windows installer from Node.js website Here is the download link for Node.js v0.6.6
Install it is pretty straight forward
Add two entries to Windows' PATH environment variable to call node and npm from anywhere in the command line
On Windows 32-bit "%PROGRAMFILES%\nodejs";"%APPDATA%\npm"
On Windows 64-bit "%PROGRAMFILES(X86)%\nodejs";"%APPDATA%\npm"
You can then install certain Node.js packages* with NPM, for example, coffee-script
npm install -g coffee-script
The packages will be installed in %APPDATA%\npm
Running coffee-script to watch and compile your file
coffee -w -o app.coffee
Pretty neat!
*Some packages will not run, for example, socketstream. After install it globally, you can create a new app using socketstream new test_app, but it will fail to start with the following errors:
Starting SocketStream server in single-process mode... node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ TypeError: Cannot call method 'split' of undefined at %APPDATA%\npm\node_modules\socketstream\lib\backen d\loader.coffee:73:29 at Array.forEach (native) at Object.apiTree (%APPDATA%\npm\node_modules\sockets tream\lib\backend\loader.coffee:69:27) at Object.serverSideFiles (%APPDATA%\npm\node_modules \socketstream\lib\backend\loader.coffee:26:12) at Object.<anonymous> (%APPDATA%\npm\node_modules\soc ketstream\lib\backend\worker.coffee:21:8) at Object.<anonymous> (%APPDATA%\npm\node_modules\soc ketstream\lib\backend\worker.coffee:45:4) at Module._compile (module.js:432:26) at Object..coffee (%APPDATA%\npm\node_modules\sockets tream\node_modules\coffee-script\lib\coffee-script.js:14:21) at Module.load (module.js:351:31) at Function._load (module.js:310:12)
0 notes
Text
coffee-script version 1.1.2 for OS X
The formula for coffee-script was recently updated to version 1.1.2.
To install coffee-script on your Mac, open your Terminal application and run the following commands;
brew update brew install coffee-script
The updated formula is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
require 'formula' class CoffeeScript < Formula url 'https://github.com/jashkenas/coffee-script/tarball/1.1.2' head 'https://github.com/jashkenas/coffee-script.git' homepage 'http://jashkenas.github.com/coffee-script/' md5 '9331fad15cc7fc9f5f258bbb81cd135a' # head coffee-script usually depends on head node and # since there isn't a way to specify that just remove # the depends_on depends_on 'node' unless ARGV.build_head? def install bin.mkpath system "./bin/cake", "--prefix", prefix, "install" end def caveats; <<-EOS.undent coffee-script can also be installed via `npm install coffee-script`. This has the advantage of supporting multiple versions (of any Node libs) at the same time. You may want to install coffee-script via npm. This formula may be retired from a future version of Homebrew. EOS end end
This package, coffee-script, depends on;
node
See which packages depend on coffee-script.
0 notes