Ember example for Rails developers
In response to http://stackoverflow.com/questions/15913324/what-paradigm-shifts-in-thinking-should-a-rails-or-server-side-developer-make-wh
HTML
<script src="ruby on rails"></script>
<script type="text/x-handlebars" data-template-name="application">
<h1>Ember example for Rails developers</h1>
{{outlet}}
<p class="details">See <a href="http://stackoverflow.com/questions/15913324/what-paradigm-shifts-in-thinking-should-a-rails-or-server-side-developer-make-wh">this StackOverflow post</a> for more details.</p>
</script>
<script type="text/x-handlebars" data-template-name="posts">
<ul class="posts">
{{#each controller}}
<li>{{#linkTo 'post' this}}{{title}}{{/linkTo}}</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="post">
<h2>{{title}}</h2>
<div class="body">{{body}}</div>
{{#if lowRatedCommentsShown}}
<button {{action 'hideLowRatedComments'}}>Hide Low-Rated Comments</button>
{{else}}
<button {{action 'showLowRatedComments'}}>Show Low-Rated Comments</button>
{{/if}}
{{partial "comments"}}
</script>
<script type="text/x-handlebars" data-template-name="_comments">
<ul class="commnts">
{{#each comment in comments}}
<!-- Messy logic that would be a great example of when to use
non-singleton controllers, which is an advanced topic. -->
{{#if comment.isLowRated}}
{{#if lowRatedCommentsShown}}
<li>{{comment.body}}</li>
{{/if}}
{{else}}
<li>{{comment.body}}</li>
{{/if}}
{{/each}}
</script>
CSS
.body {
margin-bottom: 16px;
}
.details {
color: darkgrey;
font-size: 80%;
}
JavaScript
window.App = Ember.Application.create();
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.FixtureAdapter.create()
});
App.Post = DS.Model.extend({
title: DS.attr("string"),
body: DS.attr("string"),
comments: DS.hasMany("App.Comment")
});
App.Comment = DS.Model.extend({
post: DS.belongsTo("App.Post"),
body: DS.attr("string"),
rating: DS.attr("number"),
isLowRated: function () {
return this.get("rating") < 2;
}.property("rating")
});
App.Post.FIXTURES = [{
id: 1,
title: "Post #1",
body: "Sample post body.",
comments: [1, 2]
}, {
id: 2,
title: "Post #2",
body: "Sample post body.",
comments: []
}];
App.Comment.FIXTURES = [{
id: 1,
post: 1,
body: "First!",
rating: 1
}, {
id: 2,
post: 1,
body: "Good point, but you need to double-check that claim in paragraph 2.",
rating: 5
}];
App.Router.map(function () {
this.route("index", { path: "/" });
this.route("posts", { path: "posts" });
this.route("post", { path: "post/:post_id" });
});
App.IndexRoute = Ember.Route.extend({
redirect: function () {
this.replaceWith("posts");
}
});
App.PostsRoute = Ember.Route.extend({
model: function (params) {
return App.Post.find();
}
});
App.PostRoute = Ember.Route.extend({
model: function (params) {
return App.Post.find(params.post_id);
}
});
App.PostController = Ember.ArrayController.extend();
App.PostController = Ember.ObjectController.extend({
// This shared between all posts for as long as the app runs (because
// this controller is a singleton), but it doesn't get saved in the database
// (because this is a controller, not a model).
lowRatedCommentsShown: false,
// Called by PostView or its template in response to an HTML event.
showLowRatedComments: function () {
this.set("lowRatedCommentsShown", true);
},
// Called by PostView or its template in response to an HTML event.
...