Rails, Postgres, Angular, and Bootstrap: The Power Stack

Rails, Postgres, Angular, and Bootstrap: The Power Stack

Rails, Postgres, Angular, and Bootstrap are all powerful technologies in and of themselves. When used together, however, you get a powerful web application development stack that reduces friction between what you want for your users and what you can deliver.

F74253f4a099258870157426b4cdb2dc?s=128

David Copeland

November 14, 2015
Tweet

Transcript

  1. Rails, Postgres, Angular, and Bootstrap The Power Stack David Bryant

    Copeland @davetron5000
  2. Journey through the “stack”

  3. Full Stack is important

  4. “Jack of all trades, master of none… …oftentimes better than

    master of one”
  5. UI

  6. None
  7. None
  8. Learn about design

  9. None
  10. MY AMAZING APP!

  11. MY AMAZING APP!

  12. Text

  13. Modular Type Scale

  14. Subhead 1 Subhead 2 Subhead 3 Body Text Captions &

    Secondary Text Heading
  15. About Us The place for all your needs We’ve got

    everything you could ever want and then some. It’s just that simple to be as awesome as we are, and it shows. You can’t find this much great stuff anywhere else, so what are you waiting for? Sign up Now! MY APP Sign Up Log In Help
  16. None
  17. None
  18. <div class="row"> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div>

    <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> <div class="col-md-1">.col-md-1</div> </div> <div class="row"> <div class="col-md-8">.col-md-8</div> <div class="col-md-4">.col-md-4</div> </div>
  19. <form class="form-horizontal"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">Email</label> <div class="col-sm-10">

    <input type="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">Password</label> <div class="col-sm-10"> <input type="password" class="form-control" id="inputPassword3" placeholder="Password"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="checkbox"> <label> <input type="checkbox"> Remember me </label> </div> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">Sign in</button> </div> </div> </form> <form> <label for="inputEmail3" class="col-sm-2 control-label">Email</label> <input type="email" class="form-control" id="inputEmail3" placeholder="Email"> <label for="inputPassword3" class="col-sm-2 control-label">Password</label> <input type="password" class="form-control" id="inputPassword3" placeholder="Password"> <label> <input type="checkbox"> Remember me </label> <button type="submit" class="btn btn-default">Sign in</button> </form>
  20. <button type=“button” class=“btn btn-default”>Default</button> <button type=“button” class=“btn btn-primary”>Primary</button> <button type=“button”

    class=“btn btn-primary btn-lg”>Large</button> <button type=“button” class=“btn btn-primary btn-xs”>XS</button> Default Default Default Default
  21. <div class=“alert alert-success”>…</div> alert-info alert-warning alert-danger

  22. Panel Icons Sub-panel Well Disabled Badge

  23. Interaction

  24. JavaScript & jQuery

  25. You shouldn’t think about locating DOM elements and firing or

    responding to events <div class=“dialog js-dismissable”> <h1>OK?</h1> <nav> <button data-dismiss=“yes”>Close</button> <button data-ok>OK</button> </nav> </div> $(“.js-dimissable”).find(“[data-ok]”).click(function() { // ... });
  26. Components & Behavior <dialog> <title>OK?</title> <dismiss>Close</dismiss> <confirm>OK</confirm> </dialog> dialog.on_confirm(function() {

    // ...
 });
  27. None
  28. Some Documentation Kinda Works No Support Yeah, there’s probably some

    code comments, and it’s entirely possible I used great variable names. Functions and objects should be consistent, but probably aren’t. I think there was a demo page somewhere, maybe? It still doesn’t handle that weird case on IE 8, and I never tested what happens if you use two containers in the same DOM subtree, but CSS polyfills mostly work for major browsers. No, there’s no test suite. I’m moving onto a project using Node, Elixir, Redis, Mongo, and Kubernetes, so the best thing to do is hang out on the Slack channel. I live in New Orleans, but work Amsterdam hours, so I’m not always around. JS
  29. None
  30. <aside class=“modal-dialog”> <h1>{{ title }}</h1> <p ng-if=“message”> {{ message }}

    </p> <button ng-click=“dismiss()”>Close</button> <button ng-click=“ok(‘ok’)”>OK</button> <button ng-click=“ok(‘maybe’)”>Maybe</button> </aside>
  31. angular.module(‘controllers’).controller( “DialogController”, function($scope, $dialog, opts) { $scope.title = opts.title; $scope.message

    = opts.message; $scope.ok = function(data) { if (data == ‘ok’) { $dialog.confirm(); } else { $dialog.confirm(withData: data) }
 } $scope.dismiss = function() { $dialog.cancel();
 } 
 });
  32. User = $resource(“/users/:id”); $scope.user = User.get(id: 1234); <article> <h1>{{ user.name

    }}</h1> <h2>{{ user.email }}</h2> <ul ng-repeat=“login in user.recentLogins”> <li> <strong>{{ login.date }}</strong> - {{ login.ipAddress }} </li> </ul> </article>
  33. angular.module(‘controllers’).controller( “DialogController”, function($scope, $dialog, opts) { $scope.title = opts.title; $scope.message

    = opts.message; $scope.ok = function(data) { if (data == ‘ok’) { $dialog.confirm(); } else { $dialog.confirm(withData: data) }
 } $scope.dismiss = function() { $dialog.cancel();
 } 
 });
  34. angular.module(“app”).factory( “customConfirmation”, function() { return { confirm: function($dialog,data) { if

    (data == ‘ok’) { $dialog.confirm(); } else { $dialog.confirm(withData: data); }
 } }
 } ); angular.module(‘controllers’).controller( “DialogController”, function($scope, $dialog, opts, customConfirmation) { $scope.title = opts.title; $scope.message = opts.message; $scope.ok = customConfirmation.confirm; $scope.dismiss = function() { $dialog.cancel();
 } 
 });
  35. Angular is Popular

  36. The “Back End”

  37. Middleware

  38. Parse HTTP Extract params, headers, cookies, etc Route to code

    Read result Generate response, cookies, headers, etc. Database Access Package Assets Run Tests Schema Management Configuration & Deployment YOUR CODE
  39. Parse HTTP Extract params, headers, cookies, etc Route to code

    Read result Generate response, cookies, headers, etc. Database Access Package Assets Run Tests Schema Management Configuration & Deployment Plumbing
  40. Your Code

  41. Don’t make decisions

  42. None
  43. None
  44. None
  45. Data

  46. Durability

  47. Integrity

  48. Speed

  49. Modeling

  50. SQL RDBMS

  51. First: Learn SQL. You won’t regret it.

  52. None
  53. ALTER TABLE users ADD CONSTRAINT valid_emails CHECK ( ( guest

    = true AND email ! ‘[A-Za-z0-9._%-]+@example.com’) OR ( guest = false AND email ~ ‘[A-Za-z0-9._%-]+@example.com’) )
  54. CREATE INDEX users_name_index ON users (lower(name)) SELECT * FROM users

    WHERE lower(name) = ‘bob’;
  55. UPDATE users SET config = ‘auto_save => true, color =>

    default’::hstore; CREATE INDEX user_config ON users USING GIN(config); ALTER TABLE users ADD COLUMN config HSTORE; SELECT * FROM users WHERE config @> ‘auto_save => true’;
  56. ALTER TABLE users ADD COLUMN roles text[]; UPDATE users SET

    roles = ‘{staff,admin}’; CREATE INDEX user_roles ON users USING GIN(roles); SELECT * FROM users WHERE roles @> ‘{admin}’;
  57. ALTER TABLE transactions ADD COLUMN braintree_response JSONB; UPDATE transactions SET

    braintree_response = ‘{ “processor_response”: “decline”, “processor_code”: 1234, “details”: { “charge_type”: “authorization”, “amount”: 12.45, “zip”: “20002” } ‘;
  58. CREATE INDEX txn_responses ON transactions USING GIN(braintree_response); SELECT * FROM

    transactions WHERE braintree_response @> ‘{“processor_response”: “decline”}’::jsonb;
  59. SQL Knowledge + Postgres == Powerful data layer

  60. Putting it all Together

  61. Be Honest about Weaknesses

  62. Bootstrap • JS-based components require jQuery • Angular-UI-Bootstrap

  63. Angular • Protractor (end-to-end testing) totally disconnected from Rails/back-end •

    Use Capybara/PhantomJS for E2E testing
  64. Rails • Strange view/front-end/JS/AJAX design • Avoid • Disable turbolinks

    • Asset Pipeline oddities • Learn to use it—it’s actually powerful
  65. Rails • Database Migrations “DSL” • You are not making

    a database-agnostic app • Use execute • Use SQL-based schema config.active_record.schema_format = :sql
  66. Rails • ActiveRecord • Examine queries in the log—look for

    optimizations • Let SQL shine • Don’t fear .where() or ActiveRecord::Base.connection.exec_query()
  67. Postgres • Stored Procedures • Triggers • Avoid putting business

    logic here
  68. You don’t have to use every feature

  69. These are powerful tools

  70. The reduce the decisions you have to make to only

    what’s important.
  71. If you are making decisions not related to your product…

  72. …consider Bootstrap, Angular, Rails, or Postgres

  73. If you want to know the details… http://full-stack-rails.com