The Emberist

Ember.js and Related Technologies

Learn More About Ember.js emberjs.com

Naming Conventions

Another common point of confusion for Ember newcomers is naming. Not only does proper naming help keep your application code cleaner, it also has an effect on your application's operation. Once you get the hang of it, it's quite simple so read on to learn more.

This post is out of date. Please refer to the Ember Naming Conventions Guide instead.

When to Capitalize

The Ember rules for capitalization are pretty straight-forward. If it's a class or a namespace, it's uppercase; if it's an instance, it's lowercase. Namespaces are the only objects that should be declared as globals, i.e. classes and instances should always be declared on a namespace. Some examples: Ember and your application are namespaces 1, Ember.Object and Ember.View are classes, and MyApp.personController and myObj are instances.

The first reason for this naming convention is that it makes it quite simple to figure out what kind of object you're dealing with. If it's lowercase, it's an instance, if it's uppercase, it's a class or namespace.

Secondly, and more important, because of this convention, Ember can make some assumptions about your code and behave more intelligently as a result.

Capitalization in Bindings

Lets work with the following code:

MyApp.controllerOne = Ember.Object.create({
  value: 'one'
});

MyApp.controllerTwo = Ember.Object.create({
  Constant: 'const',

  valueHash: {
    value: 'two'
  },

  valueBinding: 'valueHash.value',

  valueOneBinding: 'MyApp.controllerOne.value',

  constBinding: 'Constant'

});

// Sync our bindings. Not necessary in normal use.
Ember.run.sync();

MyApp.controllerTwo.get('value'); // two
MyApp.controllerTwo.get('valueOne'); // one
MyApp.controllerTwo.get('const'); // undefined

So, if you've got a basic understanding of Ember, you'll understand why value and valueOne return their respective values. However, you might be surprised to see that const returns undefined. The explanation is simple: Ember sees the capital and assumes that this must be a namespace and looks for the global Constant, which, of course, is undefined.

So what do we do if we actually want to get the local property? All we need to do is prepend this. to our binding, as such:

constBinding: 'this.Constant'

This tells Ember that we're looking for it on the current object instead of the global level.

Capitalization in Templates

Consider the following javascript:

window.myProp = 'prop';

MyApp.controllerOne = Ember.Object.create({
  value: 'one',
  Constant: 'const'
});

MyApp.controllerTwo = Ember.Object.create({
  value: 'two',
});

and template:

{{#with MyApp.controllerOne}}
  {{value}}
  {{Constant}}
  {{MyApp.controllerTwo.value}}
  {{myProp}}
{{/with}}

This outputs the following:

one const two

If you're looking carefully, you may have noticed that our behavior here varies a bit from bindings, so let me explain. When Ember encounters a bound property in a template it checks to see if that property exists in the current context, MyApp.controllerOne in this case. If the property is not defined, then Ember checks to see if it begins with an uppercase letter. If it does, then we assume it is a namespace and look for it globally. This is what happens in the case of MyApp.controllerTwo.value. Ember will not look for lowercase property names globally, i.e. myProp.

So why don't bindings check both locations like we do in templates? The main reason for this is performance. Bindings use get and getPath internally. These are both very hot code paths and having to continually check two locations adds up over time. Templates are rendered with much less frequency so a bit of extra work there doesn't end up being a problem.

More on Namespacing

Another useful trick that comes into play is creating your own namespaces. As we mentioned earlier, your app is actually a namespace as well. Ember.Application is a subclass of Ember.Namespace. You might be wondering why we need a custom namespace class. Why can't we just do MyNamespace = {}? The main benefit of Ember.Namespace comes when you attempt to inspect your objects. Let me show you:

NamespaceOne = {};
NamespaceOne.Object = Ember.Object.extend();

NamespaceTwo = Ember.Namespace.create();
NamespaceTwo.Object = Ember.Object.extend();

NamespaceOne.Object.toString(); // (subclass of Ember.Object)
NamespaceTwo.Object.toString(); // NamespaceTwo.Object

As you can see, when we use Ember.Namespace, lets toString provide us with more information about the object. We're able to do this with a bit of creative code that actually scans window for instances of Ember.Namespace and then, in turn, examines the properties of each.

Summary

If that hasn't all sunk in well, you can basically remember the following:

1. Yes, technically your application is itself an instance, but since it functions as a namespace we capitalize it as well. We'll talk about this more later.


blog comments powered by Disqus