*Or other server side MVC
A bit about me |
|
Jeremy GreenConsultantOrganizer of OkcRuby.orgAlso into drumming, photography, and brewing |
|
@jagthedrummer jeremy@octolabs.com http://www.octolabs.com/ |
Part 2 is bonus content for later.
a
tagNOT server side MVC
Many of the same terms
but sometimes they mean different things
where Ember == Rails
where Ember == Rails
Router == config/routes.rb
Connect URLs to code paths
# Rails config/routes.rb
Rails.application.routes.draw do
get 'about' => 'static_pages#about', :as => :about
end
// Ember Router
App.Router.map(function(){
this.route('about');
});
where Ember == Rails
Model == Model
Object wrapper for business data
# Rails db/schema.rb
create_table "patterns" do |t|
t.integer "p1"
t.integer "p2"
t.integer "p3"
# ...
end
class Pattern < ActiveRecord::Base
def name
"#{p1}-#{p2}-#{p3}"
end
end
where Ember == Rails
Model == Model
Object wrapper for business data
App.Pattern = DS.Model.extend({
p1 : DS.attr('number'),
p2 : DS.attr('number'),
p3 : DS.attr('number'),
name : function(){
return this.get('p1') + '-' +
this.get('p2') + '-' +
this.get('p3');
}.property('p1','p2','p3')
});
where Ember != Rails
where Ember != Rails
Rails : view == template
Ember : view != template
Template == Template
Markup for UI
Ember Views =~ JS Sprinkles
Interaction & DOM Logic
Ember Components are VERY similar
This is the place for jQuery DOM selectors and
integration with other JS libs.
where Ember != Rails
# Rails config/routes.rb
get 'about' # <-- This line is commonly called a route.
// Ember Router
this.route('about'); // <-- This line is commonly called ???
// A line in the router?
// It is NOT a Route.
where Ember != Rails
Rails : route IN the router
Ember : Route AFTER the router
where Ember != Rails
# app/controllers/pages_controller.rb
class PagesController < ApplicationController
def about
@authors = Author.all
end
end
App.AboutRoute = Ember.Route.extend({
model : function(){
return this.store.find('author');
}
});
where Ember != Rails
Route =~ GET Controller actions
Setup data for user interaction (index, new, edit, show)
where Ember != Rails
Controller =~ [POST|PUT|DELETE] Controller actions
Handle user interactions and input (create, update, delete)
where Ember != Rails
App.PatternsNewController = Ember.ObjectController.extend({
actions : {
savePattern : function(){
this.get('model').save();
this.transitionToRoute('pattern',this.get('model'));
}
}
});
Ember | =~ | Rails |
---|---|---|
Router | =~ | config/routes.rb |
Model | =~ | Model |
Template | =~ | Template |
Views | =~ | JS Sprinkles |
Route | =~ | GET Controller actions |
Controller | =~ | [POST|PUT|DELETE] Controller actions |
@jagthedrummer jeremy@octolabs.com |
# config/routes.rb
Rails.application.routes.draw do
root :to => 'static_pages#home'
end
This app is useless!
# app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
end
App = Ember.Application.create();
<script type="text/x-handlebars">
Welcome to the Pattern Lab!
Your home for procedurally generated patterns.
This is a small demo app built with Ember and Ember Data.
</script>
App = Ember.Application.create();
App.Router.map(function(){
this.route('index',{ path:'' })
});
App.IndexRoute = Ember.Route.extend({});
App.IndexController = Ember.ObjectController.extend({});
App.IndexView = Ember.View.extend({});
<script type="text/x-handlebars" id="index">
<h1>This app is verbose AND useless!</h1>
</script>
http://emberjs.jsbin.com/boyim/3/edit
<html>
<head>...</head>
<body>
This is the layout
<%= yield %>
</body>
</html>
This app is useless!
# config/routes.rb
Rails.application.routes.draw do
# ...
get 'about' => 'static_pages#about', :as => :about
end
This app has not gotten any more useful...
<%= link_to 'About', about_path %>
App.Router.map(function(){
this.route('about');
});
They can't contain much logic.
The 'map' for distinct parts of your app
gives you bookmarkable/shareable URLs within your app
handles reading/writing the URL bar
passes 'path variables' into your Route
<%= render 'layouts/footer' %>
© OctoLabs
# app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def about
@about_data = {
:version => "0.0.1"
}
end
end
About
Version : <%= @about_data[:version] %>
App.IndexRoute = Ember.Route.extend({
model : function(){
return {
version : "0.0.1"
};
}
});
# in db/schema.rb
create_table "patterns" do |t|
t.integer "p1"
t.integer "p2"
t.integer "p3"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
class Pattern < ActiveRecord::Base
def name
"#{p1}-#{p2}-#{p3}"
end
end
resources :patterns
class PatternsController < ApplicationController
def index
@patterns = Pattern.all
end
end
Latest Patterns
<% @patterns.each do |pattern| %>
- <%= pattern.name %>
<% end %>
App.Pattern = DS.Model.extend({
p1 : DS.attr('number'),
p2 : DS.attr('number'),
p3 : DS.attr('number'),
name : function(){
return this.get('p1') + '-' +
this.get('p2') + '-' +
this.get('p3');
}.property('p1','p2','p3')
});
App.Router.map(function() {
// ...
this.resource('patterns');
});
App.PatternsRoute = Ember.Route.extend({
model : function(){
return [this.store.createRecord('pattern',
{ p1 : 1, p2 : 2, :p3 : 5}
)];
}
});
App.ApplicationAdapter = DS.FixtureAdapter;
App.Pattern.reopenClass({
FIXTURES: [
{ id: 1, p1 : 1, p2 : 2, p3 : 5},
{ id: 2, p1 : 42, p2 : 142, p3 : 242},
{ id: 3, p1 : 100, p2 : 200, p3 : 300}
]
});
App.PatternsRoute = Ember.Route.extend({
model : function(){
return this.store.find('pattern');
}
});
App.Router.map(function() {
this.resource('patterns',function(){
this.resource('pattern', { path: '/:pattern_id' });
});
});
This is the place for jQuery DOM selectors and
integration with other JS libs.
Probably.
{{pattern-display pattern=model width="256" height="256"}}
App.PatternDisplayComponent = Ember.Component.extend({
drawPattern : function(){
var ch = new Chromanin(256,this.get('canvasId')),
p1 = this.get('pattern.p1'),
p2 = this.get('pattern.p2'),
p3 = this.get('pattern.p3');
ch.initlayers(256,256);
ch.checkerBoardLayer(0,16,16,p1,p2,p3,0,0,128);
ch.sineDistort(0,0,0.100000001490116,p1,p2,p3);
ch.addLayers(0,1,4,1,1);
ch.addLayers(4,2,4,1,1);
ch.addLayers(4,3,4,1,1);
ch.writeCanvas();
}
// ...
});
App.PatternDisplayComponent = Ember.Component.extend({
// ...
didInsertElement : function(){
this.drawPattern();
},
automaticUpdate : function(){
Ember.run.next(this,function(){
this.drawPattern();
});
}.observes('pattern','pattern.p1','pattern.p2','pattern.p3'),
canvasId : function(){
return "canvas-" + Math.floor((Math.random() * 1000000) + 1);;
}.property('pattern.id')
});
App.Router.map(function() {
this.resource('patterns',function(){
this.resource('pattern', { path: '/:pattern_id' });
this.route('new');
});
});
{{#link-to 'patterns.new'}}New Pattern{{/link-to}}
App.PatternsNewRoute = Ember.Route.extend({
model : function(){
return this.store.createRecord('pattern');
}
});
App.PatternsNewController = Ember.ObjectController.extend({
actions : {
savePattern : function(){
this.transitionToRoute('pattern',this.get('model'));
},
randomize : function(){
this.setProperties({
p1 : Math.floor((Math.random() * 1000) + 1),
p2 : Math.floor((Math.random() * 1000) + 1),
p3 : Math.floor((Math.random() * 1000) + 1)
});
}
}
});
Manipulaiton of models and triggering of related events.
Also a good place for transaction management.
App.ApplicationAdapter = DS.RESTAdapter.extend({
host : 'http://pattern-lab-api.herokuapp.com'
});
savePattern : function(){
var _this = this;
this.get('model').save().then(function(pattern){
_this.transitionToRoute('pattern',pattern);
});
}
http://emberjs.jsbin.com/kimoyo/2/edit
@jagthedrummer jeremy@octolabs.com |