Slide 1

Slide 1 text

Rails, Postgres, Angular, and Bootstrap The Power Stack David Bryant Copeland @davetron5000

Slide 2

Slide 2 text

Journey through the “stack”

Slide 3

Slide 3 text

Full Stack is important

Slide 4

Slide 4 text

“Jack of all trades, master of none… …oftentimes better than master of one”

Slide 5

Slide 5 text

UI

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Learn about design

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

MY AMAZING APP!

Slide 11

Slide 11 text

MY AMAZING APP!

Slide 12

Slide 12 text

Text

Slide 13

Slide 13 text

Modular Type Scale

Slide 14

Slide 14 text

Subhead 1 Subhead 2 Subhead 3 Body Text Captions & Secondary Text Heading

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-1
.col-md-8
.col-md-4

Slide 19

Slide 19 text

Email
Password
Remember me
Sign in
Email Password Remember me Sign in

Slide 20

Slide 20 text

Default Primary Large XS Default Default Default Default

Slide 21

Slide 21 text

alert-info alert-warning alert-danger

Slide 22

Slide 22 text

Panel Icons Sub-panel Well Disabled Badge

Slide 23

Slide 23 text

Interaction

Slide 24

Slide 24 text

JavaScript & jQuery

Slide 25

Slide 25 text

You shouldn’t think about locating DOM elements and firing or responding to events

OK?

Close OK
$(“.js-dimissable”).find(“[data-ok]”).click(function() { // ... });

Slide 26

Slide 26 text

Components & Behavior OK? Close OK dialog.on_confirm(function() { // ...
 });

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

{{ title }}

{{ message }}

Close OK Maybe

Slide 31

Slide 31 text

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();
 } 
 });

Slide 32

Slide 32 text

User = $resource(“/users/:id”); $scope.user = User.get(id: 1234);

{{ user.name }}

{{ user.email }}

  • {{ login.date }} - {{ login.ipAddress }}

Slide 33

Slide 33 text

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();
 } 
 });

Slide 34

Slide 34 text

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();
 } 
 });

Slide 35

Slide 35 text

Angular is Popular

Slide 36

Slide 36 text

The “Back End”

Slide 37

Slide 37 text

Middleware

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Your Code

Slide 41

Slide 41 text

Don’t make decisions

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

Data

Slide 46

Slide 46 text

Durability

Slide 47

Slide 47 text

Integrity

Slide 48

Slide 48 text

Speed

Slide 49

Slide 49 text

Modeling

Slide 50

Slide 50 text

SQL RDBMS

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

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]’) )

Slide 54

Slide 54 text

CREATE INDEX users_name_index ON users (lower(name)) SELECT * FROM users WHERE lower(name) = ‘bob’;

Slide 55

Slide 55 text

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’;

Slide 56

Slide 56 text

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}’;

Slide 57

Slide 57 text

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” } ‘;

Slide 58

Slide 58 text

CREATE INDEX txn_responses ON transactions USING GIN(braintree_response); SELECT * FROM transactions WHERE braintree_response @> ‘{“processor_response”: “decline”}’::jsonb;

Slide 59

Slide 59 text

SQL Knowledge + Postgres == Powerful data layer

Slide 60

Slide 60 text

Putting it all Together

Slide 61

Slide 61 text

Be Honest about Weaknesses

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

Angular • Protractor (end-to-end testing) totally disconnected from Rails/back-end • Use Capybara/PhantomJS for E2E testing

Slide 64

Slide 64 text

Rails • Strange view/front-end/JS/AJAX design • Avoid • Disable turbolinks • Asset Pipeline oddities • Learn to use it—it’s actually powerful

Slide 65

Slide 65 text

Rails • Database Migrations “DSL” • You are not making a database-agnostic app • Use execute • Use SQL-based schema config.active_record.schema_format = :sql

Slide 66

Slide 66 text

Rails • ActiveRecord • Examine queries in the log—look for optimizations • Let SQL shine • Don’t fear .where() or ActiveRecord::Base.connection.exec_query()

Slide 67

Slide 67 text

Postgres • Stored Procedures • Triggers • Avoid putting business logic here

Slide 68

Slide 68 text

You don’t have to use every feature

Slide 69

Slide 69 text

These are powerful tools

Slide 70

Slide 70 text

The reduce the decisions you have to make to only what’s important.

Slide 71

Slide 71 text

If you are making decisions not related to your product…

Slide 72

Slide 72 text

…consider Bootstrap, Angular, Rails, or Postgres

Slide 73

Slide 73 text

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