building bulletproof views
TRANSCRIPT
![Page 1: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/1.jpg)
* BUILDING BULLETPROOF VIEWSJOHN ATHAYDE & BRUCE WILLIAMS, LivingSocial RAILS CONF 2011 BALTIMORE, MARYLAND
![Page 2: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/2.jpg)
*
JOHNa designer(who also develops)
![Page 3: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/3.jpg)
*
BRUCEa developer(who also designs)
![Page 4: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/4.jpg)
WE WORK AT
![Page 5: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/5.jpg)
WE ARE WRITING A BOOKfor
![Page 6: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/6.jpg)
HOW MANY HERE ARE
DEVELOPERS??
![Page 7: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/7.jpg)
HOW MANY HERE ARE
DESIGNERS??
![Page 8: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/8.jpg)
BOTH?http://www.flickr.com/photos/clydeorama/5451312303/
![Page 9: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/9.jpg)
AGENDA
HOUR 1
*
Intro, SurveysViews are ComplexMarkup RefresherBuilding a Layout
Questions
![Page 10: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/10.jpg)
AGENDA
HOUR 2
*
The Art of Template WritingQuestions
![Page 11: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/11.jpg)
AGENDA
HOUR 3
*
Nailing NavigationMaintainable FormsDon’t Fear the Object
Going MobilePackaging Assets
![Page 12: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/12.jpg)
* 1.VIEWS ARECOMPLEX
![Page 13: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/13.jpg)
Views are still...
THE WILD WEST
![Page 14: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/14.jpg)
<ol class="narrow_playlist"><% playlist.listings.each_with_index do |listing, i| -%><% if i < show %>
<% composition = listing.composition %> <% position = i %>
<li class="playlist_item"> <table class="playlist_listing"> <tr> <td class="listing_rank_col"> <%= position+1 %> </td> <td class="listing_title_col"> <h6><%#= link_to awesome_truncate(composition.title,30), label_release_track_path(composition.label.slug, composition.release.slug), :title => composition.title %></h6> <h6><%= link_to awesome_truncate(composition.title,30), composition_path(composition), :title => composition.title %></h6> </td> <td class="listing_icon_col" rowspan="3"> <ul class="playlist_site_actions"> <li class="preview"> <a class="sm2_link" href="<%= composition.preview_url %>"> <span class="hide_me">Preview</span> </a> <%= link_to_function(image_tag("icon_speaker_preview.png", :alt => "Preview", :title => "Preview"), "") %> </li>
<% if !composition.member_contributed %> <li class="add_to_cart"> <% if composition.network? %> <%= link_to image_tag("button_playlist_download.gif", :alt => "Download"), downloads_path(:audio_item_id => composition.audio_items.first.id), :method => :post%> <% else %> <%= link_to(image_tag("cart.gif", :alt => "Add to cart", :title => "Add to cart"), selections_path(:salable_id => composition.id, :salable_type => composition.class.name), :method => :post) %> <% end -%> </li> <% end -%> </ul> </td> </tr> <tr> <td></td> <td><h6 class="artist"><%= linked_profiles(composition) %></h6></td> </tr> <tr> <td></td> <td> <ul class="playlist_social_actions"> <%= render :partial => "/ratings/rating_list", :locals => {:class_name => composition.class.superclass.name, :ratable => composition}%> <li> <%= link_to_function(image_tag("icon_load_in_player.png", :alt => "Add to Playlist",:title => "Add to Playlist"), "addCompositionToPlayerPlaylist(#{composition.id})") %> </li> </ul> </td> </tr> </table></li>
<% end %><% end -%></ol>
![Page 15: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/15.jpg)
QUICKLY CLEANEDMuch simpler and could be better...
<ol class="latest_uploads"> <% playlist.listings.each_with_index do |listing, i| -%> <% if i < show %> <% composition = listing.composition %> <% position = i %> <li class="playlist_item"> <p class="track_title"><%= link_to awesome_truncate(composition.title,30), composition_path(composition), :title => composition.title %></p> <p class="sm2_link"><a href="<%= composition.preview_url %>"><span class="hide_me">Preview</span> </a> <% if composition.network? %> <%= link_to image_tag("button_playlist_download.gif", :alt => "Download"), downloads_path(:audio_item_id => composition.audio_items.first.id), :method => :post%> <% else %> <%= link_to(image_tag("cart.gif", :alt => "Add to cart", :title => "Add to cart"), selections_path(:salable_id => composition.id, :salable_type => composition.class.name), :method => :post) %> <% end -%></p> <p class="artist_name"><%= linked_profiles(composition) %></p> <ul class="playlist_social_actions"> <%= render :partial => "/ratings/rating_list", :locals => {:class_name => composition.class.superclass.name, :ratable => composition}%> <li> <%= link_to_function(image_tag("icon_load_in_player.png", :alt => "Add to Playlist",:title => "Add to Playlist"), "addCompositionToPlayerPlaylist(#{composition.id})") %> </li> </ul> </li><% end %><% end -%></ol>
![Page 16: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/16.jpg)
Views are still...
THE RED-HEADEDSTEPCHILD
![Page 17: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/17.jpg)
MULTIPLE LANGUAGESMuch simpler and could be better...
➡ ERB/Ruby
➡ HTML
➡ CSS
➡ JavaScript/CoffeeScript
➡ Serialization formats
![Page 18: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/18.jpg)
LACK OF FAMILIARITY & RULES
![Page 19: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/19.jpg)
“This is really long. I should break it into partials.”
![Page 20: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/20.jpg)
“This is really complex. I should make it a helper.”
![Page 21: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/21.jpg)
http://www.flickr.com/photos/lastyearsgirl_/2882447041
DESIGNERISSUES
![Page 22: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/22.jpg)
* 2.MARKUPREFRESHER
![Page 23: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/23.jpg)
HOW MANY HERE
USE ANDUNDERSTANDHTML5?
?
![Page 24: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/24.jpg)
WHICH VERSION?HTML5 vs HTML4 vs XHTML
Newest (under development) standard. More semantic elements and other technologies
HTML5
Pretty standard.HTML4
XML version of HTML4, most browsers didn’t respect itXHTML 1.0
![Page 25: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/25.jpg)
DECLARE A DOCTYPEAnd then develop to it
HTML 4.01 StrictHTML 4.01 Transitional
HTML 4.01 FramesetXHTML 1.0 Strict
XHTML 1.0 TransitionalXHTML 1.0 Frameset
XHTML 1.1HTML (5)
www.alistapart.com/articles/doctype/
![Page 26: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/26.jpg)
XHTML 4 & HTML 4HAVE THESE ELEMENTS
html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td
![Page 27: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/27.jpg)
HTML5HAS SOME NEW SEMANTIC TOYS
section, article, header, hgroup, nav,footer, aside, time, figure, figcaption
Legacy support requires Modernizr or a javascript shiv.
and removes things like frameset and consolidatessome other elements together (acronym/abbr)
![Page 28: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/28.jpg)
HIERARCHYWhere it’s at.
![Page 29: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/29.jpg)
<div class="headline">This is a page headline.</div><div class="subhead">This is a subhead</div><div class="body">This is body text and it goes on for miles and miles. I like cheese.</div><div class="list">This is going to be a list of items:<br />- Item 1<br />- Item 2<br />- Item 3<br /></div>
NO HIERARCHYNot semantic, everything is the same.
![Page 30: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/30.jpg)
NO HIERARCHYNot semantic, everything is the same.
![Page 31: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/31.jpg)
<hgroup> <h1>This is a page headline.</h1> <h2>This is a subhead</h2></hgroup><section id=”page”> <p>This is body text and it goes on for miles and miles. I like cheese.</p> <p>This is going to be a list of items:</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul></section>
“SEMANTIC”HTML Tags used for meaning
![Page 32: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/32.jpg)
“SEMANTIC”HTML Tags used for meaning
![Page 33: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/33.jpg)
USE THE ELEMENTS!Lists are lists. Not divs with bullets.
<% @unit.unit_client_scans.each do |client_scan| %> • <%= client_scan.value %><br /><% end %>
<ul class=”scans”><% @unit.unit_client_scans.each do |client_scan| %> <li><%= client_scan.value %></li><% end %></ul>
![Page 34: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/34.jpg)
!TIP:
Mark up content for the meaning, NOT the layout. Use the semantic elements.
![Page 35: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/35.jpg)
VALIDATE!Valid HTML makes for better coding
validator.w3.org
![Page 36: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/36.jpg)
STYLECSS Overview and Legacy Hacks
http://www.flickr.com/photos/prettycooljewels/4351797285/
![Page 37: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/37.jpg)
<div class="b"> <div class="l"> <div class="r"> <div class="bl"> <div class="br"> <div class="tl"> <div class="tr box"> <%= content %> </div> </div> </div> </div> </div> </div> </div>
ROUNDED CORNERSVintage like...
![Page 38: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/38.jpg)
ROUNDED CORNERS<div class=”box-to-be-rounded”> <%= content %></div>
CSS3 Solution
.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 */}
![Page 39: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/39.jpg)
REQUIRED FIELDS
<%= f.label :first_name %> <span class=”required”>*</span><br /><%= f.text_field :first_name %>
Love the form you’re with
span.required {color: red;}
![Page 40: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/40.jpg)
REQUIRED FIELDS<%= f.label :first_name, :class => “required” %><%= f.text_field :first_name %>
Progressively enhance!
label { display: block; }
label.required { color: red; }
label.required:after { content: “*”;}
Not supported in MSIE 7 and below, 8 does not accept images for content
www.quirksmode.org/css/beforeafter.html
![Page 41: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/41.jpg)
DON’T FIGHT THE BROWSEREmbrace it!
html { overflow-y: scroll;}
![Page 42: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/42.jpg)
ID vs. CLASSThere should be a standard
#this_is_an_id
.this-is-a-class
![Page 43: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/43.jpg)
!TIP:
Embrace the browser and its flaws. Design to the power of the medium. (SCROLLING IS NOT A FLAW)
![Page 44: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/44.jpg)
SHORTENINGLearn to write concise css
http://www.flickr.com/photos/tomsaint/3456155628/
![Page 45: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/45.jpg)
CSS SHORTHANDCombine pieces together
margin-top: 4px;margin-right: 2px;margin-bottom: 4px;margin-left: 8px;
becomes...
margin: 4px 2px 4px 8px;
application.css
![Page 46: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/46.jpg)
CSS SHORTHANDCombine pieces together
background-color: #333;background-image: url(“../images/texture.png”)background-position: top left;background-repeat: repeat;
becomes...
background: #333 url(“../images/texture.png”) repeat-x top left;
application.css
![Page 47: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/47.jpg)
CSS SHORTHANDCombine pieces together
fontbackgroundmarginborderpaddinglist
CAN BE USED FOR:
Reduce stylesheet size and improve readability.
AND WILL HELP YOU
![Page 48: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/48.jpg)
HOW TO WRITE CSS.button-install { margin-left: 30px; font-family: "Helvetica Neue", helvetica, arial, sans-serif; display: block; width: 250px; margin-bottom: 15px; text-align: left; height: 48px; font-size: 20px; font-weight: bold; padding:4px 0 8px 0; background-color: #67c5e6; background-image: -webkit-gradient( linear, left top, left bottom, color-stop(0.23, rgb(103,197,230)), color-stop(0.81, rgb(94,149,167)) ); background-image: -moz-linear-gradient( center top, rgb(103,197,230) 23%, rgb(94,149,167) 81% ); border-radius: 8px; -webkit-border-radius: 8px; -moz-border-radius: 8px;}
Hard to read and find what you’re looking for...
![Page 49: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/49.jpg)
HOW TO WRITE CSS.button-install { background-color: #67c5e6; background-image: -webkit-gradient( linear, left top, left bottom, color-stop(0.23, rgb(103,197,230)), color-stop(0.81, rgb(94,149,167)) ); background-image: -moz-linear-gradient( center top, rgb(103,197,230) 23%, rgb(94,149,167) 81% ); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; display: block; font: bold 20px "Helvetica Neue", helvetica, arial, sans-serif; height: 48px; margin: 0 0 15px 30px; padding:4px 0 8px 0; text-align: left; width: 250px;}
Alpha order your properties, use shorthand, one per line
![Page 50: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/50.jpg)
!TIP:
Write effective and concise CSS. Properties in alpha order, be specific, browser experimental calls before standard calls, and don’t use browser hacks.
![Page 51: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/51.jpg)
BUT GUYS,
WHY DOESTHIS MATTER?
?
![Page 52: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/52.jpg)
WEB ACCESSIBILITYTake care of your users
![Page 53: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/53.jpg)
GOOGLE IS A BLIND USER
![Page 55: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/55.jpg)
START SMALLCover the basics all the time.
www.w3.org/TR/WCAG10/full-checklist.html
![Page 56: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/56.jpg)
WEB ACCESSIBILITYERB Examples
link_to @product.name, product_path(@product), :title => “Take a look at #{@product.name}”
image_tag “product_12758.png”, :alt => “#{@product.name}”
link_to (image_tag “product_12758.png”, :alt => “#{@product.name}”), product_path(@product), :title => “Take a look at #{@product.name}”
![Page 57: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/57.jpg)
WEB ACCESSIBILITY=Well Formed HTML
Not just an afterthought.
![Page 58: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/58.jpg)
!TIP:
HTML is code. Don’t be afraid to write it. Well written HTML helps users of all types access and interact with our content or application.
![Page 59: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/59.jpg)
* 3.BUILDINGA LAYOUT
![Page 60: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/60.jpg)
A STORY OF A LAYOUTDefault
<!DOCTYPE html><html> <head> <title></title> <%= stylesheet_link_tag :all %> <%= javascript_include_tag :defaults %> <%= csrf_meta_tag %> </head> <body> <%= yield %> </body></html>
application.html.erb
![Page 61: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/61.jpg)
CHARSETCombine pieces together
<!DOCTYPE html><html> <head> <meta charset=”utf-8”> <title></title> <%= stylesheet_link_tag :all %> <%= javascript_include_tag :defaults %> <%= csrf_meta_tag %> </head> <body> <%= yield %> </body></html>
application.html.erb
![Page 62: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/62.jpg)
TARGET MSIEBy version
<!DOCTYPE html><!--[if lt IE 7 ]> <html lang="en" class="ie ie6"> <![endif]--><!--[if IE 7 ]> <html lang="en" class="ie ie7"> <![endif]--><!--[if IE 8 ]> <html lang="en" class="ie ie8"> <![endif]--><!--[if IE 9 ]> <html lang="en" class="ie ie9"> <![endif]--><!--[if (gt IE 9)|!(IE)]><!--> <html lang="en"> <!--<![endif]-->
Extracted into a gem by Bruce
http://codefluency.com/post/1100393830/ie-conditional-tag-plugin
<%= ie_conditional_tag :html %>
application.html.erb
![Page 63: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/63.jpg)
TARGET MSIEBy version
section#page { margin: 0 auto; width: 960px;}
.ie7 section#page { overflow: hidden;}
http://codefluency.com/post/1100393830/ie-conditional-tag-plugin
application.css
![Page 64: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/64.jpg)
RECOGNIZE NEW ELEMENTSHTML5 Shiv (or Shim, same thing)
<!--[if lt IE 9]><script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
Enables the elements and fixes printing on IE
code.google.com/p/html5shiv/
![Page 65: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/65.jpg)
modernizr.com
![Page 66: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/66.jpg)
RESET.CSSGet your browser on the same page
meyerweb.com/eric/tools/css/reset/
First showed up in 2007
Put forth by Eric Meyer
NOT about defaults
Brings browsers to the same base page
Makes you specify everything
![Page 67: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/67.jpg)
RESET.CSSGet your browser on the same page
html5doctor.com/html-5-reset-stylesheet/
tml, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
outline:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
....etc...
reset.css
![Page 68: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/68.jpg)
CALLING STYLESHEETSPitfalls of :all
<%= stylesheet_link_tag :all %>
Can load things in alpha order, meaning reset happens after
Xapplication.html.erb
![Page 69: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/69.jpg)
CALLING STYLESHEETSManually calling them
<%= stylesheet_link_tag ‘reset’, ‘application’, ‘buttons’ %>
application.html.erb
![Page 70: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/70.jpg)
CALLING STYLESHEETSDefining :defaults
class Application < Rails::Application config.action_view.stylesheet_expansions[:defaults] = %w( nav tipsy iconic ui-lightness/jquery-ui-1.8.11.custom jquery.customSelect dashboard shadows dataTables/css/demo_table dataTables/css/demo_page application )end
config/application.rb
![Page 71: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/71.jpg)
FRAMEWORKS/BOILERPLATECombine pieces together
html5boilerplate.com
![Page 72: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/72.jpg)
Build Your Own
Framework
BUILD YOUROWN
FRAMEWORK
http
://www.flick
r.com/p
hoto
s/dysto
pos/3
15312
589/
![Page 73: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/73.jpg)
HIERARCHY OF H TAGSYou can reuse the H1. Really.
html|-body| |-header| | |-h1| |-article| | |-h1| | |-section| | | |-header| | | | |-h1| | | |-p| | | |-h2
![Page 74: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/74.jpg)
QUESTIONSAND ANSWERS
![Page 75: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/75.jpg)
AGENDA
HOUR 2
*
The Art of Template WritingQuestions
![Page 76: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/76.jpg)
*
WELCOMEBACK!
![Page 77: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/77.jpg)
* 4.THE ART OF TEMPLATEWRITING
![Page 78: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/78.jpg)
IMPROVINGREADABILITY
http://www.flickr.com/photos/bluefootedbooby/389279217/
![Page 79: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/79.jpg)
WHY WE REFACTOR
➡ Templates can be verbose
➡ Display logic can be very complex
➡ More people need to read, understand, and modify them.
➡ They need to change more frequently, as they’re more subjective
![Page 80: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/80.jpg)
FORMATTING
<html> <head> <title>...
Don’t indent with hard tabs
![Page 81: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/81.jpg)
FORMATTING<% pets.each do |pet| %><li> <%= pet.name %></li><% end %>
Indent
Better:
<% pets.each do |pet| %> <li> <%= pet.name %> </li><% end %>
![Page 82: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/82.jpg)
FORMATTING
<p> We believe that many dogs are unnecessarily abandoned because of easily solved, unwanted behavior. To combat this, we offer behavior classes to <strong>all<strong> adopters, and all individuals requiring help with their dogs.</p>
Clean up big blocks of text
Still try to keep line length <= 80 characters per line
![Page 83: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/83.jpg)
TIDYBecause templating code gets messy.
http://www.flickr.com/photos/muehlinghaus/3564021462/
![Page 84: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/84.jpg)
FORMATTING
$ gem install rack-tidy$ gem install rack-tidy-ffi
Output formatting isn’t your job
Use one of these (or similar) as middleware
![Page 85: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/85.jpg)
http://www.flickr.com/photos/miltonkeynesman/5359120312/
![Page 86: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/86.jpg)
Zen CodingUse a tool, not a generator
div#page>img.logo+ul#navigation>li*5>a
<div id="page"> <img src=”” class="logo" /> <ul id="navigation"> <li><a href=""></a></li> <li><a href=""></a></li> <li><a href=""></a></li> <li><a href=""></a></li> <li><a href=""></a></li> </ul></div>
PROJECT FILES:code.google.com/p/zen-coding/
![Page 87: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/87.jpg)
!TIP:
Know your team. YTMV
![Page 88: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/88.jpg)
TOOLSWhat do we use for each situation?
http://www.flickr.com/photos/anotherphotograph/3571242832/
![Page 89: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/89.jpg)
REFACTORING TOOLS
Extract part of a template (usually for reuse)PARTIALS
Extract complex logicHELPERS
Extract complex, wrap content, View DSLsBLOCK HELPERS
Reduce helper spaghetti code, encapsulate state, ease testingVIEW CLASSES
![Page 90: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/90.jpg)
QUERYING, ORDERING, LIMITING
<% Pet.all.order(:adoption_date).each do |pet| %> <%# Use pet %><% end %>
Don’t do this.
X
![Page 91: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/91.jpg)
QUERYING, ORDERING, LIMITING
def index @pets_by_adoption = Pet.all.order(:adoption_date)end
Instead, set an instance variable
pets_controller.rb
<% @pets_by_adoption.each do |pet| %> <%# Use pet %><% end %>
_adoption_list.html.erb
![Page 92: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/92.jpg)
QUERYING, ORDERING, LIMITING
def pets_by_adoption @pets_by_adoption = Pet.all.order(:adoption_date)end
Or instead, use a helper
pets_helper.rb
<% pets_by_adoption.each do |pet| %> <%# Use pet %><% end %>
_adoption_list.html.erb
![Page 93: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/93.jpg)
!TIP:
Avoid capital letters in your template code (configuration constants and model classes).
![Page 94: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/94.jpg)
LOCAL ASSIGNMENT
<% number_available = Pet.available.count %><% available, unavailable = pets_by_status %><% next_month = Date.today >> 1 %>
Don’t do this, ever. Never. At no time...
Messy, noisy, undocumentable, easy to accidentally remove
X_availability.html.erb
![Page 95: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/95.jpg)
LOCAL ASSIGNMENT
def index # ... other stuff @number_available = Pet.available.countend
Instead, use an instance varaible
pets_controller.rb
![Page 96: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/96.jpg)
LOCAL ASSIGNMENT
def number_available @number_available ||= Pet.available.countend
Or instead, use a helper
pets_helper.rb
![Page 97: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/97.jpg)
CONDITIONAL CONTENT
<% if @pet.at_risk? <%# Lots of content %><% else %> <%# Different lots of content %><% end %>
Avoid long if/else clauses
If lengthy, this makes it hard to get a quickfeeling of what the page contains.
X
![Page 98: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/98.jpg)
CONDITIONAL CONTENT
def risk_assessment if @pet.at_risk? render partial: 'at_risk' else render partial: 'not_at_risk' endend
Better, split to files
pets_helper.rb
<%= risk_assesment %>
show.html.erb
![Page 99: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/99.jpg)
CONDITIONAL CONTENT
<% if current_user.admin? || current_user.can?(:edit_pet) || pet.owner == current_user %> <%= render partial: 'form', locals: {pet: pet} %><% end %>
Avoid long and complex conditions
If lengthy, this makes it hard to get a quickfeeling of what the page contains.
X
![Page 100: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/100.jpg)
CONDITIONAL CONTENT
<% if can_edit_pet?(pet) %> <%= render partial: 'form', locals: {pet: pet}<% end %>
Better, extract condition toa meaningful helper
_pet.html.erb
![Page 101: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/101.jpg)
MANUAL LOOPS
<ul id='pets'> <% @pets.each do |pet| %> <li> <%= image_tag pet.image.url(:thumb) %> <%= pet.name %> <%= pet_stats(pet) %> <li> <% end %></ul>
Minimize theseindex.html.erb
X
![Page 102: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/102.jpg)
MANUAL LOOPS
<ul id='pets'> <%= render @pets %></ul>
Break into partials
index.html.erb
<li> <%= image_tag pet.image.url(:thumb) %> <%= pet.name %> <%= pet_stats(pet) %><li>
_pet.html.erb
![Page 103: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/103.jpg)
http://www.flickr.com
/photos/lambdacz/4
725437313
RENDERING(There are many ways to do it.)
![Page 104: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/104.jpg)
RENDERING
render partial: 'pet'
Without an object
Renders #{controller_name}/_pet.html.erb
render partial: 'pets/pet'
Always renders pets/_pet.html.erb
![Page 105: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/105.jpg)
RENDERING
render partial: 'pet', locals: {pet: pet}
With an object
Using :locals
<p><%= pet.description %></p>
Renders _pet.html.erbAssigns pet local variable
![Page 106: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/106.jpg)
RENDERING
render partial: 'pet', object: comment
With an object
Using :object
<p><%= pet.description %></p>
Also renders _pet.html.erbAssigns pet local variable
![Page 107: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/107.jpg)
RENDERING
render pet
With an object
Using an implicit partial
Checks the object’s .class.name (“Pet”), renderspets/_pet.html.erb, and assigns the object to
the local pet variable.
![Page 108: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/108.jpg)
RENDERING
<% @pets.each do |pet| %> <%= render pet %><% end %>
With a collection of objects
With a manual loop:
![Page 109: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/109.jpg)
RENDERING
render partial: 'pet', collection: @pets
With a collection of objects
Using :collection
Renders _pet.html.erb for each object in @pets,assigning each as the pet local variable
![Page 110: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/110.jpg)
RENDERING
render @pets
With a collection of objects
Using an implicit partial
Checks the object’s .class.name (“Pet”), renderspets/_pet.html.erb, and assigns each object to
the pet local variable.
![Page 111: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/111.jpg)
RENDERING
render [a_cat, a_dog, another_dog]
With a collection of objects
If we had Cat, and Dog single table inheritancesubclasses of Pet, with this render:
cats/_cat.html.erb (with cat set to a_cat)dogs/_dog.html.erb (with dog set to a_dog)dogs/_dogs.html.erb (with dog set to another_dog)
![Page 112: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/112.jpg)
!TIP:
Using implicit partial rendering means you don’t have to CARE which partial gets rendered.
![Page 113: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/113.jpg)
SETTING THE PAGE TITLEThe Instance Variable Method
Xdogs_controller.rb
def show @dog = Dog.find(params[:id]) @page_title = @dog.nameend
<section id='content'> <header id=‘page_header’> <h1><%= @page_title %></h1> </header> <%= yield %></section>
application.html.erb
![Page 114: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/114.jpg)
SETTING THE PAGE TITLE
<% content_for :page_header do %> <h1><%= @pet.name %></h1><% end %>
show.html.erb
<section id='content'> <% if content_for?(:page_header) %> <header id=‘page_header’><%= yield :page_header %></header> <% end %> <%= yield %></section>
application.html.erb
The content_for Method
![Page 115: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/115.jpg)
SETTING THE PAGE TITLE
def page_title(title) content_for(:page_header, content_tag(:h1, title))end
pets_helper.rb
<% page_title @pet.name %>
show.html.erb
The content_for Method
![Page 116: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/116.jpg)
!TIP:
Use content_for in your action templates to define content that is conceptually related to the action, but structurally located elsewhere in the layout.
![Page 117: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/117.jpg)
BLOCK HELPERS
http://www.flickr.com
/photos/icco/5237319
440/
![Page 118: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/118.jpg)
!TIP:
Don’t code generate before you have determined what your common design elements are.
![Page 119: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/119.jpg)
QUESTIONSAND ANSWERS
![Page 120: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/120.jpg)
AGENDA
HOUR 3
*
NavigationForming Forms
Don’t Fear the ObjectGoing Mobile
Packaging Assets
![Page 121: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/121.jpg)
*
WELCOMEBACK!
![Page 122: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/122.jpg)
* 5.NAILINGNAVIGATION
![Page 123: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/123.jpg)
WHAT NAVIGATION DOES
➡ Tells users where they can go
➡ Reminds them where they are
![Page 124: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/124.jpg)
WHERE ARE WE?The Instance Variable Method
Xdogs_controller.rb
def show @dog = Dog.find(params[:id]) @current_tab = :dogsend
<ul> <li class=’<%= nav_class(:dogs) %>’> <%= link_to ‘Dogs’, dogs_path %> </li> ...</ul>
def nav_class(tab) ‘active’ if tab == @current_tabend
application_helper.rb
_nav.html.erb
![Page 125: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/125.jpg)
WHERE ARE WE?The Manual Method
X_nav.html.erb
<ul> <li> <%= link_to_unless_current("Home", action: ‘home’, controller: ‘pages’) %> </li> ...</ul>
![Page 126: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/126.jpg)
WHERE ARE WE?The CSS Method
Xapplication.html.erb
<body class="<%= controller_name %> <%= action_name %>">
nav.css
body.dogs li#dogs_tab { background: #fff;}
body.dogs li#dogs_tab a { color: #000;}
_nav.html.erb<ul> <li id=‘dogs_tab’> <%= link_to("Dogs", dogs_path) %> </li> ...</ul>
nav.css
![Page 127: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/127.jpg)
IT’S THE ACTION TEMPLATE’S
RESPONSIBILITY.
![Page 128: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/128.jpg)
*
GOOSEa simple navigation gem
GITHUB:github.com/bruce/goose
![Page 129: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/129.jpg)
USING GOOSE
<% content_for :main_nav do %> <nav id='main-nav'> <ul> <%= nav_to 'Home', root_path %> <%= nav_to 'Dogs', dogs_path %> <%= nav_to 'Cats', dogs_path %> <%= nav_to 'Contact Us', about_path %> </ul> </nav><% end %>
nav/_main.html.erbHooking it in
<header> <%= yield :main_nav %></header>
application.html.erb
![Page 130: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/130.jpg)
USING GOOSE
nav.css
Styling
nav#main_nav ul { height: 30px; overflow: hidden;}
nav#main_nav ul li { color: #999; float: left; margin-right: 3px; padding: 5px 10px;}
nav#main_nav ul li.active { color: #000; font-weight: bold;}
![Page 131: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/131.jpg)
USING GOOSE
show.html.erb
In Action Templates
<% nav_at ‘Dogs’ %>
![Page 132: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/132.jpg)
!TIP:
Driving the state of the page from the action template gives you flexibility and means you know exactly where to look to make changes.
![Page 133: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/133.jpg)
* 6.MAINTAINABLEFORMS
![Page 134: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/134.jpg)
FORM_FOR vs FORM_TAG
![Page 135: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/135.jpg)
SHOW ME!
![Page 136: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/136.jpg)
HTML5 FORM ELEMENTS
Will affect keyboard layout on iOS devices
<input type=”email” name=”email”>
diveintohtml5.org/forms.html
![Page 137: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/137.jpg)
Search
HTML5 FORM ELEMENTS<input type=”search” name=”search”>
diveintohtml5.org/forms.html
![Page 138: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/138.jpg)
Date
HTML5 FORM ELEMENTS
Only in Opera right now
<input type=”date” name=”date”>
diveintohtml5.org/forms.html
![Page 139: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/139.jpg)
FORMTASTIC
<%= form_for @adoption_application do |f| %> <fieldset> <legend>Your Name</legend> <ol> <li> <%= f.label :first_name, "First Name" %> <%= f.text_field :first_name %> </li> <li> <%= f.label :last_name, "Last Name" %> <%= f.text_field :last_name %> </li> </ol> </fieldset><% end %>
Before...
![Page 140: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/140.jpg)
FORMTASTIC
<%= semantic_form_for @adoption_application do |f| %> <%= f.inputs “Your Name” do %> <%= f.input :first_name, label: ‘First Name’ %> <%= f.input :last_name, label: ‘Last Name’ %> <% end %> ...<% end %>
After
![Page 141: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/141.jpg)
* 6.DON’T FEARTHE OBJECT
![Page 142: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/142.jpg)
YOU MAKE CLASSES FOR THE MODEL
LAYER
![Page 143: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/143.jpg)
YOU MAKE CLASSES FOR THE
CONTROLLER LAYER
![Page 144: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/144.jpg)
WHAT ABOUT THE VIEW LAYER?
![Page 145: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/145.jpg)
ENCAPSULATION
http://www.flickr.com
/photos/shuffle-art/28102475
09/
![Page 146: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/146.jpg)
HELPER CLASSEncapsulates state, accesses template
class PetHistory
def initialize(template, pet) @template = template @pet = pet end
# ...
def to_s # @template.render, etc end
end
def history @history ||= PetHistory.new(self, @pet)end
lib/pet_history.rb
pets_helper.rb
![Page 147: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/147.jpg)
HYBRIDController -> View
class PetSort delegate :params, to: :@controller delegate :each, to: :records
def initializer(controller) @controller = controller end
def field params[:field] || :name end
def order params[:order] || :desc end
private
def records # TODO: make sure field & order are on whitelist Pet.order("#{field} #{order}") end end
lib/pet_sort.rb
![Page 148: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/148.jpg)
HYBRIDController -> View
def sort @sort ||= PetSort.new(self)endhelper_method :sort
pets_controller.rb
![Page 149: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/149.jpg)
!TIP:
View classes allow you to more easily test complex logic (instantiate, stub out the controller, template, etc).
![Page 150: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/150.jpg)
* 8.GOINGMOBILE
![Page 151: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/151.jpg)
MOBILE USERINTERACTION
http://www.flickr.com
/photos/yourdon/359975
3183/
![Page 152: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/152.jpg)
MOBILE USER INTERACTION
➡ Task focused
➡ What are they trying to do?
➡ Fat-fingering (easy targets)
➡ Sometimes low bandwidth
![Page 153: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/153.jpg)
CSS3 MEDIA QUERIES
![Page 154: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/154.jpg)
Client-side smart rendering via conditional CSS
RESPONSIVE DESIGN
www.alistapart.com/articles/responsive-web-design
![Page 155: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/155.jpg)
Client-side smart rendering via conditional CSS
RESPONSIVE DESIGN
@media screen and (max-width: 800px) { }
@media screen and (max-width: 640px) { }
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) { }
If lengthy, this makes it hard to get a quickfeeling of what the page contains.
application.css
![Page 156: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/156.jpg)
www.mediaqueri.es
![Page 157: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/157.jpg)
@media QUERIES PITFALLS
➡ All content is loaded, even if it’s not shown
➡ Interaction is different on mobile
➡ Doesn’t get into the capabilities of the mobile device
![Page 158: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/158.jpg)
MOBILE SPECIFIC
TEMPLATEShttp://www.flickr.com
/photos/goincase/49738
479
49/
![Page 159: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/159.jpg)
Is it a mobile request?
MOBILE-SPECIFIC TEMPLATES
def mobile_request? request.user_agent =~ /iP(?:one|ad|od)/endhelper_method :mobile_request?
application_controller.rb
![Page 160: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/160.jpg)
SET A MIME TYPE
Mime::Type.register_alias "text/html", :mobile
mime_types.rb
![Page 161: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/161.jpg)
FILTER THE REQUEST
before_filter :prepare_mobile_request!
def prepare_mobile_request! if mobile_request? request.format = :mobile endend
application_controller.rb
![Page 162: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/162.jpg)
Specific to mobile
LAYOUT FILE
<!DOCTYPE html> <html lang="en"> <head> <title>Dam App: Mobile Edition!</title> </head> <body> <%= yield %> <%= render partial: 'layouts/footer' %> </body> </html>
application.mobile.erb
![Page 163: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/163.jpg)
LET USERS DECIDE
before_filter :set_preferred_view! before_filter :prepare_mobile_request!
def set_preferred_view! if mobile_request? case params[:prefer_view] when 'standard' session[:preferred_view] = :standard when 'mobile' session[:preferred_view] = :mobile end endend
application_controller.rb
![Page 164: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/164.jpg)
LET USERS DECIDEdef prepare_mobile_request! if mobile_request? && preferred_view == :mobile request.format = :mobile endend
def preferred_view if mobile_request? session[:preferred_view] || :mobile else :standard endend
helper_method :preferred_view
application_controller.rb
![Page 165: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/165.jpg)
LET USERS DECIDE
def link_to_prefer_view(name) link_to_unless(preferred_view == name, "#{name.capitalize} View", prefer_view: name)end
application_helper.rb
<% if mobile_request? %> <%= link_to_prefer_view :mobile %> | <%= link_to_prefer_view :standard %><% end %>
_footer.html.erb
![Page 166: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/166.jpg)
MOBILE FU
http://www.flickr.com
/photos/mfl/2
978
0314
49/
![Page 167: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/167.jpg)
![Page 168: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/168.jpg)
!TIP:
Figure out what your users need and then build to that. The technology follows the use case.
![Page 169: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/169.jpg)
* 9.PACKAGINGASSETS
![Page 170: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/170.jpg)
WHY DOES IT LOAD SLOW?YSlow and PageSpeed
![Page 171: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/171.jpg)
UNUSED SELECTORSUI side: Dust Me Selectors
sitepoint.com/dustmeselectors
![Page 172: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/172.jpg)
UNUSED SELECTORSGem: Deadweight
# lib/tasks/deadweight.rake
require 'deadweight'
Deadweight::RakeTask.new do |dw| dw.mechanize = true
dw.root = 'http://staging.example.com'
dw.stylesheets = %w( /stylesheets/style.css )
dw.pages = %w( / /page/1 /about )
dw.pages << proc { fetch('/login') form = agent.page.forms.first form.username = 'username' form.password = 'password' agent.submit(form) fetch('/secret-page') }
dw.ignore_selectors = /hover|lightbox|superimposed_kittens/ end
www.github.com/aanand/deadweight
![Page 173: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/173.jpg)
A MORE ROBUST METHODthat covers javascript too...
“Jammit is an industrial strength asset packaging library for Rails, providing both the CSS and JavaScript concatenation and compression that you'd expect,
as well as YUI Compressor and Closure Compiler compatibility, ahead-of-time gzipping, built-in JavaScript template support, and optional Data-URI /
MHTML image and font embedding.”
documentcloud.github.com/jammit
![Page 174: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/174.jpg)
Concat, Convert, Minify assets
RAILS 3.1 SPROCKETS
vendor/assetsapp/assets
![Page 175: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/175.jpg)
FINAL Q&AFIRE WHEN READY.
![Page 176: Building Bulletproof Views](https://reader030.vdocuments.mx/reader030/viewer/2022021009/6203a90eda24ad121e4bfc5b/html5/thumbnails/176.jpg)
*SLIDES:www.therailsview.com/railsconf2011
THANKYou
BOOK:www.therailsview.com/book