Slide 1

Slide 1 text

THE RAILS VIEW: THE JUNK DRAWER GROWS UP JOHN ATHAYDE & BRUCE WILLIAMS, LivingSocial SCOTTISH RUBY CONFERENCE 29 JUN 2012

Slide 2

Slide 2 text

http://www.flickr.com/photos/marirn/6131270109/

Slide 3

Slide 3 text

Background THE DUDES ABIDE

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

http://www.flickr.com/photos/marirn/6131270109/

Slide 7

Slide 7 text

http://www.flickr.com/photos/marirn/6131270109/

Slide 8

Slide 8 text

VIEW ARCHAEOLOGY FINDING THE GEMS IN THE JUNK

Slide 9

Slide 9 text

LAZY GENERATION SCAFFOLD WHAT?

Slide 10

Slide 10 text

bash$ rails g scaffold fightingwords index show kickcoder OH NO, NOT AGAIN

Slide 11

Slide 11 text

http://www.flickr.com/photos/97629199@N00/4610544557/

Slide 12

Slide 12 text

active_scaffold :client do |config|

Slide 13

Slide 13 text

http://www.flickr.com/photos/kutluhancelik/3928343101/

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

Broken gets fixed; Crappy [code] lasts forever.

Slide 16

Slide 16 text

LEGACY CODE WE STARTED THIS IN RAILS 0.9

Slide 17

Slide 17 text

<%= content %>
ROUNDED CORNERS http://frst.in/~lX Vintage.

Slide 18

Slide 18 text

ROUNDED CORNERS
<%= content %>
.box-to-be-rounded { border: 1px solid #ccc; -webkit-border-radius: 5px; /* Safari, Chrome */ -moz-border-radius: 5px; /* Firefox */ border-radius: 5px; /* IE9, Opera 10.5, else */ } CSS3 To The Rescue!

Slide 19

Slide 19 text

if elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif elsif else end

Slide 20

Slide 20 text

WHERE IS THAT PARTIAL?!?

Slide 21

Slide 21 text

THE SEVEN DEADLY VIEW SINS THINGS TO AVOID AT ALL COSTS

Slide 22

Slide 22 text

I USING TABS instead of spaces

Slide 23

Slide 23 text

II INLINE STYLES class + extract

Slide 24

Slide 24 text

III DIVITIS use the HTML elements

Slide 25

Slide 25 text

IV ASSIGNMENT use helpers, content_for

Slide 26

Slide 26 text

V INLINE JAVASCRIPT go unobstrusive

Slide 27

Slide 27 text

VI SCAFFOLDING you need to make your own

Slide 28

Slide 28 text

VII BAD FILE LOCATIONS use the conventions

Slide 29

Slide 29 text

EVERYTHING IN ITS RIGHT PLACE http://www.flickr.com/photos/ellasdad/425813314/

Slide 30

Slide 30 text

THE ASSET PIPELINE IS THERE FOR A REASON

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

THE RAILS VIEW RULES LEARN THEM LIVE THEM LOVE THEM

Slide 33

Slide 33 text

RULE # Our markup should have meaning. We write templates using semantic HTML. 1

Slide 34

Slide 34 text

HIERARCHY WHERE IT’S AT.

Slide 35

Slide 35 text

This is a page headline.
This is a section head
This is body text and it goes on for miles and miles. I like cheese.
This is going to be a list of items:
- Item 1
- Item 2
- Item 3
NO HIERARCHY Not semantic, everything is the same.

Slide 36

Slide 36 text

NO HIERARCHY Not semantic, everything is the same.

Slide 37

Slide 37 text

This is a page headline.

This is a section head

This is body text and it goes on for miles and miles. I like cheese.

This is going to be a list of items:

  • Item 1
  • Item 2
  • Item 3
SEMANTIC HTML Tags used for meaning.

Slide 38

Slide 38 text

SEMANTIC HTML Tags used for meaning.

Slide 39

Slide 39 text

VALIDATE! Valid code makes everyone happy. ONLINE: validator.w3.org

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Google is a blind user. http://www.flickr.com/photos/scooter811/1475730494/

Slide 42

Slide 42 text

START SMALL Cover the basics all the time. WAI Level 1 Checklist: www.w3.org/TR/WCAG10/full-checklist.html

Slide 43

Slide 43 text

Our style sheets should handle presentation. We don’t use markup to style or use images when CSS will do. RULE #2

Slide 44

Slide 44 text

SCSS/Sass

Slide 45

Slide 45 text

// Mixin w/ Color Maths // ------------------------------------------------------------------ @mixin buttonBackground($startColor, $endColor) { // gradientBar will set the background to a pleasing blend of these, to support IE<=9 @include gradientBar($startColor, $endColor); @include reset-filter(); // in these cases the gradient won't cover the background, so we override &:hover, &:active, &.active { background-color: $endColor; } &.disabled, &[disabled] { &:hover { @include gradientBar($startColor, $endColor); @include reset-filter(); } } // IE 7 + 8 can't handle box-shadow to show active, so we darken a bit ourselves &:active, &.active { background-color: darken($endColor, 10%) #{"\9"}; @include gradientBar($endColor, $startColor); } }

Slide 46

Slide 46 text

Our templates should be free of client-side code. We unobtrusively attach behavior from our JavaScript files RULE #3

Slide 47

Slide 47 text

data-remote is the magic word COMMONLY KNOWN AS :remote => true

Slide 48

Slide 48 text

READ rails.js WE’D SAY DO IT NOW, BUT WE’RE ON A SCHEDULE

Slide 49

Slide 49 text

PUT IT IN A FILE

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Our templates should be easy to read. We consistently indent correctly using spaces instead of tabs, type lines no longer than 80 characters, and extract complex logic to helpers and presenters. RULE #4

Slide 52

Slide 52 text

Writing HTML

Slide 53

Slide 53 text

<%= link_to client.name, client_path, :class => “client login”, :target => “_blank WAT.

Slide 54

Slide 54 text

<%= link_to client.name, client_path, :class => “client login”, :target => “_blank” %> BETTER.

Slide 55

Slide 55 text

<%= link_to_client(@client) %> SUPER.

Slide 56

Slide 56 text

<%= client_presenter.pretty_link %> HAWT.

Slide 57

Slide 57 text

INLINE PARTIAL HELPER HELPER CALLING PARTIAL PRESENTER/ DECORATOR TOO MUCH MARKUP TOO MUCH LOGIC IT GENERATES TOO MUCH MARKUP IT’S TOO HARD TO RENDER IT’S TOO MANY MOVING PARTS

Slide 58

Slide 58 text

Presenters

Slide 59

Slide 59 text

DEFINE. class PersonPresenter def initialize(person) @person = person end def signup_info info = “#{@person.signup_source} signup” if @person.referrer info << “, referred by #{@person.referrer.name}” end info end # ... end

Slide 60

Slide 60 text

INSTANTIATE. def person_presenter @person_presenter ||= PersonPresenter.new(@person) end def person_presenter(person = @person) PersonPresenter.new(person) end def person_presenter(person = @person, &block) PersonPresenter.new(person).tap do |presenter| yield presenter if block_given? end end

Slide 61

Slide 61 text

ENABLE. class PersonPresenter def initialize(view, person) @v = view @person = person end # ... end def person_presenter(person = @person, &block) PersonPresenter.new(self, person) end

Slide 62

Slide 62 text

GENERATE. class PersonPresenter # ... def link @v.link_to @person.full_name, @person end def to_s @v.render @person end end <%= person_presenter.link %> <%= person_presenter %>

Slide 63

Slide 63 text

GENERATE. class PersonPresenter # ... def link @v.link_to @person.full_name, @person end def to_s @v.render @person end end <%= person_presenter.link %> <%= person_presenter %>

Slide 64

Slide 64 text

AGGREGATE. class RankingPresenter def initialize(view, *people) @v = view @people = people end def with_grades(since = 1.month.ago, &block) # calculate scores, yield, generate, etc end end

Slide 65

Slide 65 text

CODE CLEAN, NOT CLEVER. ALL THE USUAL RULES APPLY

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

https://github.com/jcasimir/draper

Slide 68

Slide 68 text

gem ‘draper’ $rails g draper:install $rails g draper:decorator Client

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

<% if location.present? %> Located in <%= @client.location %> <% else %> Location Unknown <% end %>

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

Our templates should be easy to find. We use standard naming conventions and place them in the directory for the related resource (or the layout). RULE #5

Slide 75

Slide 75 text

render @clients

Slide 76

Slide 76 text

SHARING PARTIALS

Slide 77

Slide 77 text

Our markup should be easy for the entire team to modify. We prefer rendering partials over generating markup from Ruby code. RULE #6

Slide 78

Slide 78 text

def full_name(person) raw “

#{person.first_name} #{person.last_name}

” end BAD.

Slide 79

Slide 79 text

def full_name(person) “#{person.first_name} #{person.last_name}” end MODEL?

Slide 80

Slide 80 text

Our technology choices should help, not hinder, the team. We use the templating language and tools that work best for all of us. RULE #7

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

#profile .left.column #date= print_date #address= current_user.address .right.column #email= current_user.email #bio= current_user.bio
<%= print_date %>
<%= current_user.address %>
<%= current_user.email %>
<%= current_user.bio %>
BAKE OFF <%= ERB %>

Slide 83

Slide 83 text

#profile .left.column #date= print_date #address= current_user.address .right.column #email= current_user.email #bio= current_user.bio
<%= print_date %>
<%= current_user.address %>
<%= current_user.email %>
<%= current_user.bio %>
<%= ERB %> BAKE OFF

Slide 84

Slide 84 text

DIV

Slide 85

Slide 85 text

DIV DIV DIV DIV

Slide 86

Slide 86 text

DIV DIV DIV DIV IV DI

Slide 87

Slide 87 text

DIV DIV DIV DIV IV DI (OMG.) DI

Slide 88

Slide 88 text

%section #profile .left.column %p #date= print_date %p #address= current_user.address .right.column %p #email= current_user.email %p #bio= current_user.bio

<%= print_date %>

<%= current_user.address %>

<%= current_user.email %>

<%= current_user.bio %>

HAVE YOUR CAKE AND... <%= ERB %>

Slide 89

Slide 89 text

SOLUTION: Maybe the templating language isn’t the problem. Maybe you are. Refactor your views.

Slide 90

Slide 90 text

Our designs for the Web should work on a variety of devices and browsers. We build for the simplest interactions first and support progressive enhancement. RULE #8

Slide 91

Slide 91 text

SO MANY DEVICES (and browsers) 320px != 2650px

Slide 92

Slide 92 text

.profile { color: #ccc; margin: 20px; padding: 5px 10px; width: 300px; } .ie6 .profile { margin: 18px; }

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

Media Queries

Slide 95

Slide 95 text

.profile { color: #ccc; margin: 20px; padding: 5px 10px; width: 300px; } .ie6 .profile { margin: 18px; } @media screen and (device-width: 1024px) and (orientation:landscape) { body { font-size: 70%; } .profile { width: 50%; } }

Slide 96

Slide 96 text

http://www.mediaqueri.es

Slide 97

Slide 97 text

http://www.abookapart.com

Slide 98

Slide 98 text

http://www.abookapart.com

Slide 99

Slide 99 text

Our designs for email must work for a wide range of providers. We use HTML tables and images as necessary and always provide a plain-text alternative. RULE #9

Slide 100

Slide 100 text

TABLES SUCK TELL ’EM RAY

Slide 101

Slide 101 text

EXCEPT FOR EMAIL http://www.flickr.com/photos/gregoryjordan/6118863684/

Slide 102

Slide 102 text

No content

Slide 103

Slide 103 text

SOLUTION: Tables are not for layout unless it’s tabular data or unless you’re doing HTML emails, and then all sins are forgiven.

Slide 104

Slide 104 text

Our application should perform as well as it needs to, when it needs to. We implement the most elegant approach first, then we optimize when necessary. RULE #10

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

GET THEM ALL! http://www.therailsview.com/rules.pdf

Slide 107

Slide 107 text

BE CURIOUS http://www.flickr.com/photos/30431232@N03/3733840669

Slide 108

Slide 108 text

THANK You @therailsview TWITTER www.therailsview.com WEB ScottishRailsView BOOK CODE FOR 25% OFF AT www.pragprog.com/titles/warv: @boboroshi @wbruce