Cet article est publié sous licence CC BY-NC-SA
EmberJS est un framework javascript MVC, le code est disponible sur leur dépôt Github. D’un point de vue historique, EmberJS est issu de SproutCore ou plus précisément de SproutCore 2.
Ce framework s’utilise côté client, tout comme BackboneJS. Il permet de gérer les actions utilisateur sur une page sans rechargement et permet donc de créer des one-page-applications.
Les sites ou applications web utilisant ce genre de framework (Angular, Ember, Backbone…) disposent d’une API (créée avec le langage de votre choix, dans notre cas ce sera Ruby via le framework Ruby On Rails) afin de s’interfacer avec une base de données. EmberJS n’est pas déstiné à gérer l’accès à la base de données, il est là pour faciliter le rendu des pages et les interactions avec l’utilisateur.
La version 1.0 de ce framework est sortie le 31 août 2013, on peut donc considérer qu’il est suffisamment utilisé et testé pour nous y mettre nous aussi.
A travers une série d’articles, nous allons essayer de nous familiariser avec EmberJS. Nous irons progressivement vers des choses un peu plus complexes, cet article n’étant qu’une présentation du framework.
EmberJS a un intérêt lorsque l’on souhaite développer une application comportant une part de javascript assez conséquente. A l’heure actuelle, de plus en plus d’applications évitent les rechargements de pages au maximum afin de rendre plus fluide la navigation pour l’utilisateur.
Attention tout de même, ce n’est pas parce que vous utilisez EmberJS que tous vos soucis seront réglés. On peut très bien imaginer une application web utilisant EmberJS et qui, pour autant, n’est pas fluide du tout si l’on ne fait pas les choses correctement. Ce n’est pas forcément le temps rendu d’une page (après rechargement) qui est problématique. Cela peut également venir du temps de traitement des requêtes vers la base de données ou bien d’autres choses.
Il arrive fréquemment que l’on doive mettre à jour uniquement une partie de notre page après une action utilisateur, comme, par exemple, modifier le nom de l’utilisateur à tous les endroits où on le retrouve sur la page après une soumission de formulaire d’édition de profil. Pour ce genre de comportement, EmberJS propose des fonctionnalités qui vous seront très utiles comme nous le verrons par la suite.
Comme nous l’avons précisé plus tôt dans l’article, il vous faudra, la plupart du temps, utiliser une API afin de fournir des données à EmberJS. Utilisant Rails dans tous mes projets de développement je ne vais donc pas changer mes habitudes ici mais vous pouvez très bien utiliser EmberJS avec un autre langage.
De nombreuses ressources sont disponibles sur le net si vous souhaitez combiner EmberJS à un autre langage que Ruby.
Il est possible d’intégrer EmberJS dans une application Ruby On Rails grâce à la gem ember-rails. L’un des principaux cas d’utilisation va donc être de développer une API avec Rails et gérer l’interface avec EmberJS. C’est la combinaison de ces deux outils qui va nous intéresser principalement dans cette série d’articles.
Comme dis précédemment, une gem est disponible afin d’utiliser EmberJS dans une application Rails, il suffit donc, dans un premier temps, de l’ajouter au Gemfile de votre application (plusieurs gems sont nécessaires) :
gem 'ember-rails' gem 'ember-source'
Lancez la commande bundle install afin de finaliser l’installation du framework javascript. Ensuite, une commande existe afin de créer le squelette et les fichiers nécessaires à l’utilisation d’EmberJS :
rails g ember:bootstrap
Si vous utilisez CoffeeScript (jetez un œil à notre présentation de coffeescript si ce n’est pas le cas), il est possible de le spécifier pour générer des fichiers .coffee plutôt que .js :
rails g ember:bootstrap --javascript-engine coffee
Vous pouvez constater qu’un certain nombre de fichiers et de répertoires ont été créés dans le répertoire app/assets de votre application Rails. Lorsque l’on observe la structure d’une application utilisant EmberJS on retrouve des éléments communs à tous les frameworks MVC : des modèles, des controllers, des fichiers de vue/templates… on n’est donc pas dépaysé par rapport à Rails.
Comme nous venons de le voir, il est possible de passer différentes options à la commande permettant de générer le squelette :
--ember-path # spécifier le chemin d'ember (équivalent : -d) --skip-git # ne pas créer les fichiers .gitkeep (équivalent : -g) --javascript-engine # spécifier le langage (js ou coffee) --app-name # spcifier un nom d'application personnalisé (équivalent : -n)
Il est possible de définir d’autres options pour Ember dans le fichier config/application.rb et même de différencier ces options suivant l’environnement dans lequel on se trouve en utilisant les fichiers correspondant à chacun des environnements (config/development.rb, config/staging.rb, config/production.rb…). Voici la liste des options disponibles :
config.ember.variant # spécifier un environnement à Ember (valeurs possibles : :development ou :production).
config.ember.app_name # spécifier le nom de l'application (il sera utilisé par les générateurs)
config.ember.ember_path # spécifier un chemin spécifique aux générateurs
config.handlebars.precompile # activer/désactiver la pré-compilation (par défaut : true)
config.handlebars.templates_root # spécifier le chemin du répertoire (dans app/assets/javascripts) où se trouveront les templates (par défaut : 'templates')
config.handlebars.templates_path_separator # spécifier le séparateur pour les urls dans les templates (par défaut : '/')
config.handlebars.output_type # spécifier le style des outputs (valeurs possibles : :global, :amd, par défaut : :global)
Si vous configurez comme valeur pour l’option variant :development alors vous pourrez constater que vous avez des debugger dans la console javascript de votre navigateur. Il existe par ailleurs un plugin pour Chrome afin d’obtenir un débogueur plus complet.
Afin de tester que votre application fonctionne correctement, vous pouvez ajouter un logger qui sera appelé après le chargement d’Ember :
# dans votre fichier app/assets/javascripts/application.js ou application.js.coffee
window.MyAppName = Ember.Application.create(
ready: ->
console.log 'Hello world !' # ou quelque chose de plus original si vous le souhaitez
)
Si ce message s’affiche dans la console alors vous avez une application configurée et prête pour l’utilisation d’EmberJS, nous allons voir ce qu’il est possible de faire. Si ce message ne s’affiche pas, vérifiez bien la configuration d’Ember et qu’il n’y a pas d’erreur dans votre manifest javascript.
Il n’y a rien de mieux, pour maîtriser un nouvel outil, que de s’en servir. Nous allons donc commencer par un cas d’utilisation très simple d’EmberJS.
Afin de pouvoir jouer un peu avec EmberJS nous allons créer une nouvelle application Rails avec uniquement un model (nommé ici Team). Après avoir ajouté une route et une vue (qui peut être vide) pour la homepage et les routes et le controller pour le model créé nous allons pouvoir commencer à nous servir d’Ember.
# app/controllers/home_controller.rb
class HomeController < ApplicationController
def index
end
end
# app/controllers/teams_controller.rb
class TeamsController < ApplicationController
respond_to :json
def index
respond_with Team.all
end
end
# app/models/team.rb
class Team < ActiveRecord::Base
attr_accessible :city, :country, :name
end
# config/routes
MyAppName::Application.routes.draw do
root :to => 'home#index'
resources :teams
end
Dans un premier temps, nous allons ajouter une route dans le router d’EmberJS pour avoir une url afin de voir nos Teams :
# app/assets/javascripts/router.js.coffee
MyAppName.Router.map () ->
@resource('teams')
Ceci va nous permettre d’accèder à l’url http://localhost:3000/#/teams
qui listera les Teams présentent. Ensuite, nous créons le model EmberJS correspondant :
# app/assets/javascripts/models/team.js.coffee
MyAppName.Team = DS.Model.extend
name: DS.attr('string')
city: DS.attr('string')
country: DS.attr('string')
Enfin, il faut ajouter un fichier de routes spécifique pour le model en question :
# app/assets/javascripts/routes/teams.js.coffee
MyAppName.TeamsRoute = Ember.Route.extend
model: ->
@store.find('team')
Il ne manque maintenant plus que le fichier de template pour afficher les informations souhaitées :
Liste des équipes
<ul>
{{#each}}
<li>
{{name}} ({{city}} - {{country}})
</li>
{{/each}}
</ul>
Il ne reste plus qu’à préciser à Ember comment récupérer les données. Dans un premier temps, nous allons utiliser des fixtures car nous n’avons pas encore de données en base. De plus, les fixtures sont très simples à utiliser :
# app/assets/javascripts/store.js.coffee
MyAppName.Adapter = DS.FixtureAdapter.extend()
MyAppName.Store = DS.Store.extend
adapter: MyAppName.Adapter
Attention, ici, nous n’avons pas encore créé de fixtures mais seulement indiqué à Ember que nous en utiliserons, il faut donc aller les créer et pour cela il suffit d’ajouter les lignes suivantes dans le fichier correspondant au model EmberJS de Team :
# app/assets/javascripts/models/team.js.coffee
...
MyAppName.Team.FIXTURES = [
{
id: 1,
name: "Foo",
city: "Lille",
country: "France"
},
{
id: 2,
name: "Bar",
city: "Caen",
country: "France"
},
{
id: 3,
name: "Baz",
city: "Paris",
country: "France"
}
]
Nous avons maintenant tout ce qu’il faut pour afficher notre premier contenu avec EmberJS :
Si maintenant vous souhaitez récupérer des données créées en base, il vous faut modifier le fichier app/assets/javascripts/store.js.coffee
pour spécifier le bon adapter :
# app/assets/javascripts/store.js.coffee
MyAppName.Adapter = DS.RESTAdapter.extend()
MyAppName.Store = DS.Store.extend
adapter: MyAppName.Adapter
Après avoir créé un enregistrement en base pour le model Team, si vous relancer votre serveur et que vous actualiser la page http://localhost:3000/#/teams
vous pourrez constater qu’il y a bien un li
mais aucun contenu. A l’aide du debugger EmberJS de Chrome on peut constater qu’on récupère bien un enregistrement mais que tous ses champs sont vides. En observant les requêtes envoyées au serveur on constate qu’un appel est effectué vers http://localhost:3000/teams
et que des données sont retournées en JSON. L’adapter DS.RESTAdapter attend un format de JSON spécifique qui n’est pas celui renvoyé par défaut par Rails il faut donc spécifier le format du JSON dans Rails. Pour cela j’ai ajouté la gem active_model_serializers à mon Gemfile :
gem 'active_model_serializers', github: 'rails-api/active_model_serializers'
Ensuite, il suffit de créer le serializer pour le model souhaité :
class TeamSerializer < ActiveModel::Serializer
attributes :id,
:name,
:city,
:country
end
Et voilà, le tour est joué. Si vous relancer une dernière fois votre serveur et réactualisez votre page vous verrez bien les informations de l’objet renvoyé par le controller.
Ce premier aperçu d’EmberJS est assez convaincant. J’ai eu pour habitude d’utiliser BackboneJS jusqu’ici et malgré que je m’en sois toujours sorti je n’ai pas complètement accroché avec ce framework, ce qui m’a d’ailleurs poussé à aller voir EmberJS.
On peut, de toute façon, trouver certaines similitudes entre les deux frameworks. Cela va être intéressant de continuer à manipuler EmberJS pour faire des choses un peu plus poussées que ce qui a été fait ici afin de vraiment se faire une opinion.
Si vous avez utilisé ou utilisez EmberJS n’hésitez pas à nous faire part de votre avis ici. Idem si vous utilisez Backbone ou Angular, cela permettra peut être de comparer les usages ainsi que les avantages et inconvénients de chacun.
L’équipe Synbioz.
Libres d’être ensemble.
Nos conseils et ressources pour vos développements produit.