Slide 1

Slide 1 text

Blow Up Your Views Jeff Casimir / @j3 Thursday, September 22, 11

Slide 2

Slide 2 text

2 Your Views Suck, So What? Thursday, September 22, 11

Slide 3

Slide 3 text

3 Templating is Hard Thursday, September 22, 11

Slide 4

Slide 4 text

3 Templating is Hard ■ HTML ■ CSS ■ JavaScript ■ Ruby Thursday, September 22, 11

Slide 5

Slide 5 text

Instance Variables are Stupid 4 Thursday, September 22, 11

Slide 6

Slide 6 text

5 First, A Puzzle Thursday, September 22, 11

Slide 7

Slide 7 text

5 First, A Puzzle = self.inspect Thursday, September 22, 11

Slide 8

Slide 8 text

5 First, A Puzzle JkYmI2NGQ2ZGQ5ODVhMDRlODFJIhBfY3NyZl90b2tlbgY7AEZJIjE2TFNER1BrMXhBN0RVYzFVUkt3ek9GcnBM c29vUC9CVDF1aGs0UVJ4QUQ4PQY7AEY%3D--6d75dba5938dbe9ccd2201dd3288846e3a56f64e", "rack.request.cookie_hash"=>{"_jsblogger_session"=>"BAh7B0kiD3Nlc3Npb25faWQGOgZFRiIlZTFkNDRmYzBlYjBk NmJkYmI2NGQ2ZGQ5ODVhMDRlODFJIhBfY3NyZl90b2tlbgY7AEZJIjE2TFNER1BrMXhBN0RVYzFVUkt3ek9Gcn BMc29vUC9CVDF1aGs0UVJ4QUQ4PQY7AEY=--6d75dba5938dbe9ccd2201dd3288846e3a56f64e"}, "action_dispatch.cookies"=>{"_jsblogger_session"=>"BAh7B0kiD3Nlc3Npb25faWQGOgZFRiIlZTFkNDRmYzBlYjBk NmJkYmI2NGQ2ZGQ5ODVhMDRlODFJIhBfY3NyZl90b2tlbgY7AEZJIjE2TFNER1BrMXhBN0RVYzFVUkt3ek9Gcn BMc29vUC9CVDF1aGs0UVJ4QUQ4PQY7AEY=--6d75dba5938dbe9ccd2201dd3288846e3a56f64e"}, "action_dispatch.request.unsigned_session_cookie"=>{"session_id"=>"e1d44fc0eb0d6bdbb64d6dd985a04e81", "_csrf_token"=>"6LSDGPk1xA7DUc1URKwzOFrpLsooP/BT1uhk4QRxAD8="}, "action_dispatch.request.path_parameters"=>{:controller=>"articles", :action=>"index"}, "action_controller.instance"=>#, "action_dispatch.request.content_type"=>nil, "action_dispatch.request.request_parameters"=>{}, "rack.request.query_string"=>"", "rack.request.query_hash"=>{}, "action_dispatch.request.query_parameters"=>{}, "action_dispatch.request.parameters"=>{"controller"=>"articles", "action"=>"index"}, "action_dispatch.request.formats"=>[text/html]}, @lookup_context=#, @details={:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]}, @skip_default_locale=false, @frozen_formats=true, @view_paths=[/Users/jcasimir/RubymineProjects/jsblogger/app/ views]>, @_action_name="index", @_response_body=nil, @_config={}, @_params={"controller"=>"articles", "action"=>"index"}, @articles=[#, #, #, #, #]>> self.inspect.length == 51496 Thursday, September 22, 11

Slide 9

Slide 9 text

6 Rails MVC, Theory Thursday, September 22, 11

Slide 10

Slide 10 text

6 Rails MVC, Theory Request Controller Model View Database Router Response Thursday, September 22, 11

Slide 11

Slide 11 text

7 Rails MVC, Reality Request Request Processing Data Formatting Database Router Response Data Interface Template Rendering Persistence Translation Business Logics Thursday, September 22, 11

Slide 12

Slide 12 text

Data Interface 8 Controller supplies data to views Views format data via helpers Template injects data into HTML Generating HTML in Rails Template Rendering Data Formatting Thursday, September 22, 11

Slide 13

Slide 13 text

The Line between “C” & “V” 9 Thursday, September 22, 11

Slide 14

Slide 14 text

Data Interface 10 The Cake is a Lie Thursday, September 22, 11

Slide 15

Slide 15 text

Data Interface 10 The Cake is a Lie Interface A common means for unrelated objects to communicate with each other. These are definitions of methods and values which the objects agree upon in order to cooperate. Thursday, September 22, 11

Slide 16

Slide 16 text

Data Interface 10 The Cake is a Lie The Controller and View template pretend to share context, but really the instance variables are just copied from one to another. Interface A common means for unrelated objects to communicate with each other. These are definitions of methods and values which the objects agree upon in order to cooperate. Thursday, September 22, 11

Slide 17

Slide 17 text

Data Interface 10 The Cake is a Lie The Controller and View template pretend to share context, but really the instance variables are just copied from one to another. This is not an interface, it is tight coupling Interface A common means for unrelated objects to communicate with each other. These are definitions of methods and values which the objects agree upon in order to cooperate. Thursday, September 22, 11

Slide 18

Slide 18 text

11 A Real Interface Thursday, September 22, 11

Slide 19

Slide 19 text

11 A Real Interface Thursday, September 22, 11

Slide 20

Slide 20 text

class ArticlesController < ApplicationController def index @articles = Article.order :created_at end def show @article = Article.find(params[:id]) end end %h1 Articles = render @articles 12 A Real Interface %h1= @article.title %p= @article.body Thursday, September 22, 11

Slide 21

Slide 21 text

class ArticlesController < ApplicationController def index @articles = Article.order :created_at end def show @article = Article.find(params[:id]) end end %h1 Articles = render @articles 12 A Real Interface class ArticlesController < ApplicationController expose(:articles){ Article.order :created_at } expose(:article) def index end def show end end %h1= @article.title %p= @article.body Thursday, September 22, 11

Slide 22

Slide 22 text

class ArticlesController < ApplicationController def index @articles = Article.order :created_at end def show @article = Article.find(params[:id]) end end %h1 Articles = render @articles 12 A Real Interface class ArticlesController < ApplicationController expose(:articles){ Article.order :created_at } expose(:article) def index end def show end end %h1 Articles = render articles %h1= @article.title %p= @article.body %h1= article.title %p= article.body Thursday, September 22, 11

Slide 23

Slide 23 text

13 Decent Exposure Wins ■ Defined interface between views and controllers ■ Simplifies much of the controller logic ■ No more instance variable litter Thursday, September 22, 11

Slide 24

Slide 24 text

Kill Helpers 14 Thursday, September 22, 11

Slide 25

Slide 25 text

Objects 15 Thursday, September 22, 11

Slide 26

Slide 26 text

Objects 15 ■ In Ruby, “everything is an object” Thursday, September 22, 11

Slide 27

Slide 27 text

Objects 15 ■ In Ruby, “everything is an object” ■ In Rails, we use objects everywhere Thursday, September 22, 11

Slide 28

Slide 28 text

Objects 15 ■ In Ruby, “everything is an object” ■ In Rails, we use objects everywhere ■ Then, at the very last minute, we get procedural? Thursday, September 22, 11

Slide 29

Slide 29 text

Data Processing 16 Thursday, September 22, 11

Slide 30

Slide 30 text

Data Processing 16 ■ Hypothetical: object-neutral data processing ■ Ex: formatting timestamps for all models Thursday, September 22, 11

Slide 31

Slide 31 text

Data Processing 16 ■ Hypothetical: object-neutral data processing ■ Ex: formatting timestamps for all models ■ Reality: Object specific data processing ■ Ex: Convert a user object to a printable name Thursday, September 22, 11

Slide 32

Slide 32 text

Just Use Objects 17 Instead of using helpers like this.... Thursday, September 22, 11

Slide 33

Slide 33 text

Just Use Objects 17 = print_name(user) Instead of using helpers like this.... Thursday, September 22, 11

Slide 34

Slide 34 text

Just Use Objects 17 = print_name(user) = user.print_name Instead of using helpers like this.... How about having model-like methods... Thursday, September 22, 11

Slide 35

Slide 35 text

Just Use Objects 17 = print_name(user) = user.print_name = format_time(user.created_at) = user.created_at Instead of using helpers like this.... How about having model-like methods... Thursday, September 22, 11

Slide 36

Slide 36 text

Data Formatting 18 Rails MVC, Reality Request Request Processing Database Router Response Data Interface Template Rendering Persistence Translation Business Logic Thursday, September 22, 11

Slide 37

Slide 37 text

Data Formatting 18 Rails MVC, Reality Request Request Processing Database Router Response Data Interface Template Rendering Persistence Translation Business Logic Thursday, September 22, 11

Slide 38

Slide 38 text

Decorator / Presenter 18 Rails MVC, Reality Request Request Processing Database Router Response Data Interface Template Rendering Persistence Translation Business Logic Thursday, September 22, 11

Slide 39

Slide 39 text

Decorator Pattern 19 Thursday, September 22, 11

Slide 40

Slide 40 text

Decorator Pattern 19 ■ Take in a data model Thursday, September 22, 11

Slide 41

Slide 41 text

Decorator Pattern 19 ■ Take in a data model ■ Decorate it with view-specific methods Thursday, September 22, 11

Slide 42

Slide 42 text

Decorator Pattern 19 ■ Take in a data model ■ Decorate it with view-specific methods ■ Make use of Rails helpers like link_to and content_tag Thursday, September 22, 11

Slide 43

Slide 43 text

View Objects Implemented 20 Thursday, September 22, 11

Slide 44

Slide 44 text

View Objects Implemented 20 ■ Create an /app/decorators folder Thursday, September 22, 11

Slide 45

Slide 45 text

View Objects Implemented 20 ■ Create an /app/decorators folder ■ Create object-specific decorator classes Thursday, September 22, 11

Slide 46

Slide 46 text

View Objects Implemented 20 ■ Create an /app/decorators folder ■ Create object-specific decorator classes ■ Wrap the data object with the decorator Thursday, September 22, 11

Slide 47

Slide 47 text

Solving Other Problems 21 Thursday, September 22, 11

Slide 48

Slide 48 text

Solving Other Problems 21 ■ Preparing alternate representations with to_xml and to_json while respecting authorization Thursday, September 22, 11

Slide 49

Slide 49 text

Solving Other Problems 21 ■ Preparing alternate representations with to_xml and to_json while respecting authorization ■ Enforcing an interface, like attr_accessible for your views Thursday, September 22, 11

Slide 50

Slide 50 text

22 Draper Thursday, September 22, 11

Slide 51

Slide 51 text

22 Draper Thursday, September 22, 11

Slide 52

Slide 52 text

23 Draper

<%= product.title %>

<%= product.description %>

<%= product.price %>

<%= product.stock %>

Updated: <%= product.updated_at %>

<%= product.links %>

Thursday, September 22, 11

Slide 53

Slide 53 text

24 Draper

<%= product.title %>

<%= product.description %>

<%= product.price %>

<%= product.stock %>

Updated: <%= product.updated_at %>

<%= product.links %>

Thursday, September 22, 11

Slide 54

Slide 54 text

25 Draper class ProductsController < ApplicationController #... def show @product = ProductDecorator.find(params[:id]) end #... end Thursday, September 22, 11

Slide 55

Slide 55 text

26 Draper class ProductDecorator < ApplicationDecorator decorates :product def price number_to_currency(model.price) end def delete_link link_to "Destroy", self, :confirm => 'Are you sure?', :method => :delete end Thursday, September 22, 11

Slide 56

Slide 56 text

27 Draper :confirm => 'Are you sure?', :method => :delete end def edit_link link_to "Edit", edit_product_path(self) end def index_link link_to "View All", products_path end def stock if model.stock > 0 content_tag :span, "In Stock (#{model.stock})", :class => "in_stock" else content_tag :span, "Out of Thursday, September 22, 11

Slide 57

Slide 57 text

28 Draper end end def to_json(*args) {:title => model.title, :price => price, :stock => stock, :description => model.description, :created_at => created_at, :updated_at => updated_at, :edit => edit_link, :delete => delete_link, :index => index_link }.to_json end end Thursday, September 22, 11

Slide 58

Slide 58 text

29 Draper

<%= product.title %>

<%= product.description %>

<%= product.price %>

<%= product.stock %>

Updated: <%= product.updated_at %>

<%= product.links %>

Thursday, September 22, 11

Slide 59

Slide 59 text

Views as API Customers 30 Thursday, September 22, 11

Slide 60

Slide 60 text

31 “Web Sites” Thursday, September 22, 11

Slide 61

Slide 61 text

31 “Web Sites” Thursday, September 22, 11

Slide 62

Slide 62 text

32 What if controllers didn’t care about output format? Thursday, September 22, 11

Slide 63

Slide 63 text

33 Traditional Sequence Client Server Time Thursday, September 22, 11

Slide 64

Slide 64 text

33 Traditional Sequence Request Router Controller Data Formatting Template Rendering JavaScript Processing Model Database JS Assets Response Client Server Time Thursday, September 22, 11

Slide 65

Slide 65 text

34 Splitting Responsibilities Thursday, September 22, 11

Slide 66

Slide 66 text

34 ■ Controller provides a defined interface Splitting Responsibilities Thursday, September 22, 11

Slide 67

Slide 67 text

34 ■ Controller provides a defined interface ■ Decorator layer consumes data, prepares formatted output Splitting Responsibilities Thursday, September 22, 11

Slide 68

Slide 68 text

34 ■ Controller provides a defined interface ■ Decorator layer consumes data, prepares formatted output ■ Client receives decorated JSON and a template in HTML/JavaScript Splitting Responsibilities Thursday, September 22, 11

Slide 69

Slide 69 text

34 ■ Controller provides a defined interface ■ Decorator layer consumes data, prepares formatted output ■ Client receives decorated JSON and a template in HTML/JavaScript ■ Client renders the template with the data Splitting Responsibilities Thursday, September 22, 11

Slide 70

Slide 70 text

35 Client Side Rendering Client Server Time Thursday, September 22, 11

Slide 71

Slide 71 text

35 Client Side Rendering Request Router Controller JS Template JS Assets JavaScript Processing Model Database Data Response JS Template Client Server JS Assets Time Thursday, September 22, 11

Slide 72

Slide 72 text

Rethinking Templating 36 Thursday, September 22, 11

Slide 73

Slide 73 text

37 Rails 3.1 Flushing Thursday, September 22, 11

Slide 74

Slide 74 text

37 Rails 3.1 Flushing Thursday, September 22, 11

Slide 75

Slide 75 text

Time 38 Client-Side Rendering with Flushing Client Server Thursday, September 22, 11

Slide 76

Slide 76 text

Time 38 Client-Side Rendering with Flushing Request Router Controller JS Assets Data Formatting Asset Response JavaScript Processing Model Database JS Template Data Response Template Response Client Server Thursday, September 22, 11

Slide 77

Slide 77 text

39 How do we do it? Thursday, September 22, 11

Slide 78

Slide 78 text

■ Write interface methods in the Controller that... 39 How do we do it? Thursday, September 22, 11

Slide 79

Slide 79 text

■ Write interface methods in the Controller that... ■ Retrieve data from the model 39 How do we do it? Thursday, September 22, 11

Slide 80

Slide 80 text

■ Write interface methods in the Controller that... ■ Retrieve data from the model ■ Render out JSON 39 How do we do it? Thursday, September 22, 11

Slide 81

Slide 81 text

■ Write interface methods in the Controller that... ■ Retrieve data from the model ■ Render out JSON ■ Pass to the client 39 How do we do it? Thursday, September 22, 11

Slide 82

Slide 82 text

■ Write interface methods in the Controller that... ■ Retrieve data from the model ■ Render out JSON ■ Pass to the client ■ A rendering engine 39 How do we do it? Thursday, September 22, 11

Slide 83

Slide 83 text

■ Write interface methods in the Controller that... ■ Retrieve data from the model ■ Render out JSON ■ Pass to the client ■ A rendering engine ■ The template 39 How do we do it? Thursday, September 22, 11

Slide 84

Slide 84 text

■ Write interface methods in the Controller that... ■ Retrieve data from the model ■ Render out JSON ■ Pass to the client ■ A rendering engine ■ The template ■ The data 39 How do we do it? Thursday, September 22, 11

Slide 85

Slide 85 text

40 Rendering Engine? Thursday, September 22, 11

Slide 86

Slide 86 text

■ Plain HTML with jQuery Replacement 40 Rendering Engine? Thursday, September 22, 11

Slide 87

Slide 87 text

■ Plain HTML with jQuery Replacement ■ Mustache 40 Rendering Engine? Thursday, September 22, 11

Slide 88

Slide 88 text

■ Plain HTML with jQuery Replacement ■ Mustache ■ Handlebars (SproutCore) 40 Rendering Engine? Thursday, September 22, 11

Slide 89

Slide 89 text

■ Plain HTML with jQuery Replacement ■ Mustache ■ Handlebars (SproutCore) ■ ICanHazJS (seriously) 40 Rendering Engine? Thursday, September 22, 11

Slide 90

Slide 90 text

41 Achievements Thursday, September 22, 11

Slide 91

Slide 91 text

■ Less processing work on the server side means more requests per second 41 Achievements Thursday, September 22, 11

Slide 92

Slide 92 text

■ Less processing work on the server side means more requests per second ■ Parallelizing database access with asset feeding speeds up time to first response 41 Achievements Thursday, September 22, 11

Slide 93

Slide 93 text

■ Less processing work on the server side means more requests per second ■ Parallelizing database access with asset feeding speeds up time to first response ■ Views become API customers, unifying the data interface 41 Achievements Thursday, September 22, 11

Slide 94

Slide 94 text

42 Blow Up Your Views Thursday, September 22, 11

Slide 95

Slide 95 text

■ Instance variables are stupid, use a proper interface ■ Kill helpers and use decorator objects ■ Unify controllers and treat views as API customers ■ Use JavaScript to render templates on the client 42 Blow Up Your Views Jeff Casimir / @j3 Thursday, September 22, 11