Slide 1

Slide 1 text

To copy Rails, you must believe. Why the Rails way is still fresh. ON CHOICES

Slide 2

Slide 2 text

Includes a database-agnostic ORM with browser (memory) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same on both the client and server, modeled after Rails. The routing API is pretty much exactly like Rails 3's. Templates work on client and server as well (and you can swap in any template engine no problem). Includes asset pipeline that works just like Rails 3's - mini es and gzips assets with an md5-hashed name, only if you so desire. “ TOWERJS.ORG

Slide 3

Slide 3 text

Includes a database-agnostic ORM with browser (memory) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same on both the client and server, modeled after Rails. The routing API is pretty much exactly like Rails 3's. Templates work on client and server as well (and you can swap in any template engine no problem). Includes asset pipeline that works just like Rails 3's - mini es and gzips assets with an md5-hashed name, only if you so desire. “ TOWERJS.ORG

Slide 4

Slide 4 text

Includes a database-agnostic ORM with browser (memory) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same on both the client and server, modeled after Rails. The routing API is pretty much exactly like Rails 3's. Templates work on client and server as well (and you can swap in any template engine no problem). Includes asset pipeline that works just like Rails 3's - mini es and gzips assets with an md5-hashed name, only if you so desire. “ TOWERJS.ORG

Slide 5

Slide 5 text

Includes a database-agnostic ORM with browser (memory) and MongoDB support, modeled after ActiveRecord and Mongoid for Ruby. Includes a controller architecture that works the same on both the client and server, modeled after Rails. The routing API is pretty much exactly like Rails 3's. Templates work on client and server as well (and you can swap in any template engine no problem). Includes asset pipeline that works just like Rails 3's - mini es and gzips assets with an md5-hashed name, only if you so desire. “ TOWERJS.ORG

Slide 6

Slide 6 text

RUBY ON RAILS.

Slide 7

Slide 7 text

PHILOSOPHY.

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

Rails is not obsolete because the core principles that make it Rails are still controversial. “ ME, RIGHT NOW.

Slide 11

Slide 11 text

IT'S JUST A JSON API.

Slide 12

Slide 12 text

BUILD IT IN NODE.

Slide 13

Slide 13 text

BUILD IT IN NODE.

Slide 14

Slide 14 text

BUILD IT IN NODE.

Slide 15

Slide 15 text

BUILD IT IN NODE.

Slide 16

Slide 16 text

BUILD IT IN NODE.

Slide 17

Slide 17 text

BUILD IT IN NODE.

Slide 18

Slide 18 text

BASIC AUTH.

Slide 19

Slide 19 text

/** * Constructor function for the Bookmark object.. * @constructor * @param {connection} database: Connection to CouchDB */ var Bookmark = exports.Bookmark = function (database) { this.database = database; }; /** * Lists all Bookmarks in the database * @param {function} callback: Callback function */ Bookmark.prototype.list = function (callback) { this.database.view('Bookmark/all', function (err, result) { if (err) { return callback(err); } callback(null, result.rows.map(function (row) { return row.value })); }) }; ... MODELS.

Slide 20

Slide 20 text

exports.createRouter = function (resource) { return new (journey.Router)(function (map) { map.path(/\/bookmarks/, function () { // // LIST: GET to /bookmarks lists all bookmarks // this.get().bind(function (res) { resource.list(function (err, bookmarks) { if (err) { return res.send(500, {}, { error: err.error }); } res.send(200, {}, { bookmarks: bookmarks }); }); }); // // SHOW: GET to /bookmarks/:id shows the details of a specific bookmark // this.get(/\/([\w|\d|\-|\_]+)/).bind(function (res, id) { resource.show(id, function (err, bookmark) { if (err) { return res.send(500, {}, { error: err.error }); } res.send(200, {}, { bookmark: bookmark }); }); }); ... THE ROUTER.

Slide 21

Slide 21 text

Node is just immature. They'll get to it eventually. “ NODE APOLOGISTS.

Slide 22

Slide 22 text

THE RAILS PHILOSOPHY IS STILL CONTROVERSIAL.

Slide 23

Slide 23 text

There's More Than One Way To Do It It's common for folks just getting started to treat the examples listed on this page as some sort of gospel truth. In fact, Backbone.js is intended to be fairly agnostic about many common patterns in client- side code. For example... “ BACKBONEJS.COM

Slide 24

Slide 24 text

References between Models and Views can be handled several ways. Some people like to have direct pointers, where views correspond 1:1 with models (model.view and view.model). Others prefer to have intermediate "controller" objects that orchestrate the creation and organization of views into a hierarchy. Others still prefer the evented approach, and always re events instead of calling methods directly. All of these styles work well. “ BACKBONEJS.COM

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

MOST TECHNOLOGY COMMUNITIES DISAGREE WITH RAILS.

Slide 31

Slide 31 text

(ESPECIALLY NEW ONES)

Slide 32

Slide 32 text

IT'S NOT IMMATURITY.

Slide 33

Slide 33 text

IT'S A DESIGN DECISION.

Slide 34

Slide 34 text

CARGO CULT.

Slide 35

Slide 35 text

WHEN CLONING RAILS, THE FEATURES DON'T MATTER.

Slide 36

Slide 36 text

ONLY ONE PRIORITY.

Slide 37

Slide 37 text

SO HOW ARE WE DOING THESE DAYS?

Slide 38

Slide 38 text

MOSTLY OK

Slide 39

Slide 39 text

POINTS OF FAILURE

Slide 40

Slide 40 text

INSTALLATION.

Slide 41

Slide 41 text

$ sudo gem install rails $ rails new app $ cd app $ rails server REALITY.

Slide 42

Slide 42 text

PERCEIVED.

Slide 43

Slide 43 text

$ cat Gemfile source 'https://rubygems.org' gem 'rails', '3.2.2' # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' gem 'sqlite3' gem 'json' # Gems used only for assets and not required # in production environments by default. group :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' # See https://github.com/sstephenson/execjs#readme for more supported runtimes # gem 'therubyracer' gem 'uglifier', '>= 1.0.3' end CAVEAT.

Slide 44

Slide 44 text

ANOTHER CAVEAT.

Slide 45

Slide 45 text

WHAT WE NEED TO DO

Slide 46

Slide 46 text

BINARY RUBY.

Slide 47

Slide 47 text

BINARY GEMS.

Slide 48

Slide 48 text

OSX USERS ARE LIKE WINDOWS USERS.

Slide 49

Slide 49 text

EVEN MORE?

Slide 50

Slide 50 text

DEV MODE

Slide 51

Slide 51 text

BUILDING ASSET COMPILATION INTO RAILS IS WHAT RAILS IS ALL ABOUT.

Slide 52

Slide 52 text

IT'S TOO SLOW.

Slide 53

Slide 53 text

BOOTING RAILS IS TOO SLOW.

Slide 54

Slide 54 text

HARD PROBLEMS, NOT STUPIDITY.

Slide 55

Slide 55 text

SOLVING HARD PROBLEMS IS OUR JOB.

Slide 56

Slide 56 text

BUNDLER

Slide 57

Slide 57 text

$ rake foo rake aborted! You have already activated rake 0.9.3.beta.1, but your Gemfile requires rake 0.9.2.2. Using bundle exec may solve this. DID YOU MEAN?

Slide 58

Slide 58 text

$ rake foo rake aborted! You have already activated rake 0.9.3.beta.1, but your Gemfile requires rake 0.9.2.2. Trying bundle exec... DID YOU MEAN?

Slide 59

Slide 59 text

THINGS MAY BE HARDER THAN THEY LOOK.

Slide 60

Slide 60 text

WHAT ABOUT JS-HEAVY APPS?

Slide 61

Slide 61 text

TRADITIONAL RAILS. Model Controller Template

Slide 62

Slide 62 text

RAILS WITH JS. Model Controller Template Browser

Slide 63

Slide 63 text

TRADITIONAL RAILS. Model Controller Template @post = Post.find(1)

Slide 64

Slide 64 text

RAILS WITH JS. Model Controller Template Browser { post: { ... } }

Slide 65

Slide 65 text

TRANSFERRING REPRESENTATIONS OF RESOURCES.

Slide 66

Slide 66 text

IN MEMORY IS EASY.

Slide 67

Slide 67 text

ACROSS THE NETWORK IS HARDER.

Slide 68

Slide 68 text

THE PROBLEM IS THE SAME.

Slide 69

Slide 69 text

CONVENTION OVER CONFIGURATION.

Slide 70

Slide 70 text

■ Include the root? ■ Include other resources in a response? ■ "Sideloading" ■ How to represent associations? ■ Avoiding duplication ■ Lazily populated ■ Bulk loading? CANONICAL.

Slide 71

Slide 71 text

{ "post": { "id": 1, "title": "First post", "body": "Body of the first post", "author_id": 1, "comments": [ 1, 2 ] }, "comments": [ { "id": 1, "body": "first!", "author_id": 1 }, { "id": 2, "body": "second", "author_id": 2 } }], "authors": [ { "id": 1, "name": "Yehuda Katz" }, { "id": 2, "name": "Tom Dale" } ] } MY OPINION.

Slide 72

Slide 72 text

{ "posts": [{ "id": 1, "title": "First post", "body": "Body of the first post", "author_id": 1, }, { "id": 2, "title": "Second post", "body": "Body of the second post", "author_id": 2 }, { "id": 3, "title": "Third post", "body": "Body of the third post", "author_id": 1 }], "authors": [ { "id": 1, "name": "Yehuda Katz" }, { "id": 2, "name": "Tom Dale" } ] } MY OPINION.

Slide 73

Slide 73 text

STANDARDIZING. Model Controller Template Browser { post: { ... } }

Slide 74

Slide 74 text

SAME PROBLEMS IN REVERSE.

Slide 75

Slide 75 text

class PostsController < ApplicationController def update if params[:id] == "bulk" response = params[:posts].map do |post| update_single(post.delete(:id), post) end else response = update_single(params[:id], params[:post]) end render json: response end private def update_single(id, attrs) post = Post.find(id) post.update_attributes(attrs) end end BULK UPDATES.

Slide 76

Slide 76 text

DRY IT UP.

Slide 77

Slide 77 text

SERIALIZERS.

Slide 78

Slide 78 text

class ApplicationSerializer < ActiveModel::Serializer embed :ids, :include => true end class PostSerializer < ApplicationSerializer attributes :id, :title, :body has_many :contacts belongs_to :author end

Slide 79

Slide 79 text

WHY ALL THIS?

Slide 80

Slide 80 text

Flexibility is overrated

Slide 81

Slide 81 text

Constraints are liberating

Slide 82

Slide 82 text

THANK YOU