$30 off During Our Annual Pro Sale. View Details »

On Choices

On Choices

Yehuda Katz

April 30, 2012
Tweet

More Decks by Yehuda Katz

Other Decks in Technology

Transcript

  1. To copy Rails, you must believe. Why the Rails way

    is still fresh. ON CHOICES
  2. 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
  3. 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
  4. 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
  5. 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
  6. RUBY ON RAILS.

  7. PHILOSOPHY.

  8. None
  9. None
  10. Rails is not obsolete because the core principles that make

    it Rails are still controversial. “ ME, RIGHT NOW.
  11. IT'S JUST A JSON API.

  12. BUILD IT IN NODE.

  13. BUILD IT IN NODE.

  14. BUILD IT IN NODE.

  15. BUILD IT IN NODE.

  16. BUILD IT IN NODE.

  17. BUILD IT IN NODE.

  18. BASIC AUTH.

  19. /** * 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.
  20. 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.
  21. Node is just immature. They'll get to it eventually. “

    NODE APOLOGISTS.
  22. THE RAILS PHILOSOPHY IS STILL CONTROVERSIAL.

  23. 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
  24. 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
  25. None
  26. None
  27. None
  28. None
  29. None
  30. MOST TECHNOLOGY COMMUNITIES DISAGREE WITH RAILS.

  31. (ESPECIALLY NEW ONES)

  32. IT'S NOT IMMATURITY.

  33. IT'S A DESIGN DECISION.

  34. CARGO CULT.

  35. WHEN CLONING RAILS, THE FEATURES DON'T MATTER.

  36. ONLY ONE PRIORITY.

  37. SO HOW ARE WE DOING THESE DAYS?

  38. MOSTLY OK

  39. POINTS OF FAILURE

  40. INSTALLATION.

  41. $ sudo gem install rails $ rails new app $

    cd app $ rails server REALITY.
  42. PERCEIVED.

  43. $ 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.
  44. ANOTHER CAVEAT.

  45. WHAT WE NEED TO DO

  46. BINARY RUBY.

  47. BINARY GEMS.

  48. OSX USERS ARE LIKE WINDOWS USERS.

  49. EVEN MORE?

  50. DEV MODE

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

    ABOUT.
  52. IT'S TOO SLOW.

  53. BOOTING RAILS IS TOO SLOW.

  54. HARD PROBLEMS, NOT STUPIDITY.

  55. SOLVING HARD PROBLEMS IS OUR JOB.

  56. BUNDLER

  57. $ 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?
  58. $ 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?
  59. THINGS MAY BE HARDER THAN THEY LOOK.

  60. WHAT ABOUT JS-HEAVY APPS?

  61. TRADITIONAL RAILS. Model Controller Template

  62. RAILS WITH JS. Model Controller Template Browser

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

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

    ... } }
  65. TRANSFERRING REPRESENTATIONS OF RESOURCES.

  66. IN MEMORY IS EASY.

  67. ACROSS THE NETWORK IS HARDER.

  68. THE PROBLEM IS THE SAME.

  69. CONVENTION OVER CONFIGURATION.

  70. ▪ Include the root? ▪ Include other resources in a

    response? ▪ "Sideloading" ▪ How to represent associations? ▪ Avoiding duplication ▪ Lazily populated ▪ Bulk loading? CANONICAL.
  71. { "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.
  72. { "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.
  73. STANDARDIZING. Model Controller Template Browser { post: { ... }

    }
  74. SAME PROBLEMS IN REVERSE.

  75. 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.
  76. DRY IT UP.

  77. SERIALIZERS.

  78. class ApplicationSerializer < ActiveModel::Serializer embed :ids, :include => true end

    class PostSerializer < ApplicationSerializer attributes :id, :title, :body has_many :contacts belongs_to :author end
  79. WHY ALL THIS?

  80. Flexibility is overrated

  81. Constraints are liberating

  82. THANK YOU