Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rails, Postgres, Angular, and Bootstrap: The Po...

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.

David Copeland

November 14, 2015
Tweet

More Decks by David Copeland

Other Decks in Programming

Transcript

  1. UI

  2. 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
  3. <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>
  4. <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>
  5. <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
  6. 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() { // ... });
  7. 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
  8. <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>
  9. 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();
 } 
 });
  10. 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>
  11. 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();
 } 
 });
  12. 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();
 } 
 });
  13. 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
  14. 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
  15. ALTER TABLE users ADD CONSTRAINT valid_emails CHECK ( ( guest

    = true AND email ! ‘[A-Za-z0-9._%-][email protected]’) OR ( guest = false AND email ~ ‘[A-Za-z0-9._%-][email protected]’) )
  16. 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’;
  17. 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}’;
  18. 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” } ‘;
  19. CREATE INDEX txn_responses ON transactions USING GIN(braintree_response); SELECT * FROM

    transactions WHERE braintree_response @> ‘{“processor_response”: “decline”}’::jsonb;
  20. Rails • Strange view/front-end/JS/AJAX design • Avoid • Disable turbolinks

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

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

    optimizations • Let SQL shine • Don’t fear .where() or ActiveRecord::Base.connection.exec_query()