Your SlideShare is downloading. ×
0
The Rails WayApproach to modern web applications with               Rails 3.2
The Performance Golden Rule80% of end-users response time isdownloading all the assets.
The Rails Way to managingassets:    HTTP Streaming   The Assets Pipeline
Assets Pipeline● Assets concatenation● Assets minification● Support for high-level languages  ○ CoffeeScript  ○ SASS● Asse...
Syntactically Awesome Stylesheets$blue: #3bbfce;$margin: 16px;.content-navigation {  border-color: $blue;  color:    darke...
CoffeeScriptclass ProfileCompetences extends Backbone.View  tagName: ul  className: inputs-select initialize: ->   @collec...
Serving Static Assets Rails by default doesnt serve static assets in           production environment.
Deploymentict-ref-cloud/     current -> ~/ict-ref-cloud/releases/20120904134910     releases/          20120904134910/    ...
Deployment                        nginx     ~/ict-ref-cloud/current/public/tmp/unicorn.ict-ref-cloud.sock                 ...
OWASP Top Ten Security Risk 1.   Injection 2.   Cross Site Scripting 3.   Broken Authentication and Session Management 4. ...
OWASP Top Ten Security Risk 1.   Injection 2.   Cross Site Scripting 3.   Broken Authentication and Session Management 4. ...
The Rails Way to security:     CSRF protection     XSS protection
Cross Site Request Forgery/app/controllers/application_controller.rbclass ApplicationController < ActionController::Base  ...
Cross Site Scripting<div id="comments">    <% @post.comments.each do |comment| %>        <div class="comment">            ...
The Rails Way to routing:  Non-Resourceful routes    Resourceful routes   SEO friendly URLs
Non-Resourceful Routesmatch products/:id => products#showGET /products/10post products => products#createPOST /productsnam...
Non-Resourceful Routesmatch photos/show => photos#show, :via => [:get, :post]match photos/:id => photos#show, :constraints...
Resourceful Routesresources :photosget /photos => photos#indexget /photos/new => photos#newpost /photos => photos#createge...
Resourceful Routesresource :profileget /profile/new => profiles#newpost /profile => profiles#createget /profile => profile...
Named Routes<%= link_to Profile, profile_path %>=> <a href="/profile">Profile</a><%= link_to Preview, @photo %>=> <a href=...
SEO Friendy URLs                                                                 <%= link_to product.name, product %>     ...
The Rails Way to viewrendering:   Response rendering   Structuring Layouts          AJAX
Response Rendering/app                                 /app    /controllers                                     /views    ...
Response Renderingclass UsersController < ApplicationController    def new        @user = User.new                        ...
Rendering Responserender   :editrender   :action => :editrender   editrender   edit.html.erbrender :template => products/e...
Rendering Responserender :inline => <p><%= @comment.content %></p>render :text => OKrender :json => @productrender :xml =>...
Content Negotiationrespond_to do |format|   format.html   format.json { render :json => @product }   format.jsend
Content Negotiationclass ProductsController < ApplicationController    respond_to :html, :json, :js      def edit        r...
Structuring Layout/app   /views      /layouts         application.html.erb (default)         users.html.erb (UsersControll...
Structuring Layout<!DOCTYPE html><head>   <title>User <%= yield :title %></title></head><html>   <body>      <%= yield %> ...
Structuring Layout<% content_for :title, @post.title %><div id="post">   <h2><%= @post.title %></h2>   <div><%= @post.cont...
View Helpersmodule ApplicationHelper   def title(title)      content_for :title, title   endend
View Helpers<% title @post.title %><div id="post">   <h2><%= @post.title %></h2>   <div><%= @post.content %></div></div>
Partials/app   /views      /products         _form.html.erb         _product.html.erb         index.html.erb         edit....
Partials/app/views/products/_product.html.erb<div class="product">   <h2><%= product.name %></h2>   <p><%= product.descrip...
Partials<h1>Products</h1><% @products.each do |product| %>   <% render products/product,      :product => product %><% end...
Partials<h1>Products</h1><% @products.each do |product| %>   <% render product %><% end %>
Partials<h1>Products</h1><% render @products %>
Partials/app/views/products/_form.html.erb<%= form_for @user do |f| %>    <div class="input">        <%= f.label :name %> ...
Partials../products/new.html.erb   ../products/edit.html.erb<h1>New Product</h1>       <h1>Edit Product</h1><div id="form"...
AJAX/app/views/products/_form.html.erb<%= form_for @user, :remote => true do |f| %>    <div class="input">        <%= f.la...
AJAX/app/controllers/products_controller.rbclass ProductsController < ApplicationController    def create        @product ...
AJAX/app/views/products/create.js.erb$(#form).html("<%= escape_javascript(render form) %>");
AJAX/app/views/products/index.html.erb<%= link_to "Delete", product, method: :delete, remote: true %><a href="/products/1"...
The Rails Way to caching:     Basic Caching      Memoization
Page Cachingclass ProductsController < ActionController  caches_page :index  def index    @products = Product.all  end  de...
Action Cachingclass ProductsController < ActionController  before_filter :authenticate_user!  caches_action :index  def in...
Fragment Caching<% cache do %>  All available products:  <% @products.each do |p| %>    <%= link_to p.name, product_url(p)...
Sweepersclass ProductSweeper < ActionController::Caching::Sweeper  observe Product  def after_create(product)    # Expire ...
Conditional GET supportclass ProductsController < ApplicationController  def show    @product = Product.find(params[:id]) ...
Memoizationclass City < ActiveRecord::Base   attr_accesible :name, :zip, :lat, :lon   def display_name      @display_name ...
The Rails Way to solvetypical problems:       N+1 Problem Fetching object in batches
N+1 Problemclass User  def recent_followers    self.followers.recent.collect do |f|      f.user.name    end  endendSelect ...
N+1 Problemclass User  def recent_followers    self.followers.recent.includes(:user).collect do |f|      f.user.name    en...
Fetching objects in JavaList<Tweet> tweets = tweetDao.findAllForUser(user);for (Tweet tweet : tweets) {    // ...}for (Twe...
Fetching objects in RailsTweet.where(user: user).find_each do |tweet|    # ...enduser.tweets.find_each(batch_size: 5000) d...
Try Rails!
Upcoming SlideShare
Loading in...5
×

The Rails Way

2,810

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,810
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
25
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Transcript of "The Rails Way"

  1. 1. The Rails WayApproach to modern web applications with Rails 3.2
  2. 2. The Performance Golden Rule80% of end-users response time isdownloading all the assets.
  3. 3. The Rails Way to managingassets: HTTP Streaming The Assets Pipeline
  4. 4. Assets Pipeline● Assets concatenation● Assets minification● Support for high-level languages ○ CoffeeScript ○ SASS● Assets fingerprinting
  5. 5. Syntactically Awesome Stylesheets$blue: #3bbfce;$margin: 16px;.content-navigation { border-color: $blue; color: darken($blue, 9%);}.border { padding: $margin / 2; margin: $margin / 2; border-color: $blue;}
  6. 6. CoffeeScriptclass ProfileCompetences extends Backbone.View tagName: ul className: inputs-select initialize: -> @collection.on(reset, @render, this) render: -> competences = @collection.competences() _.each competences, (competence) => view = new AutosaveSelectOption(model: @model, dict: competence) $(@el).append(view.render().el) this
  7. 7. Serving Static Assets Rails by default doesnt serve static assets in production environment.
  8. 8. Deploymentict-ref-cloud/ current -> ~/ict-ref-cloud/releases/20120904134910 releases/ 20120904134910/ app/ config/ database.yml -> ~/ict-ref-cloud/shared/config/database.yml public/ assets -> ~/ict-ref-cloud/shared/assets shared/ assets/ application-8e3bd046319a574dc48990673b1a4dd9.js application-8e3bd046319a574dc48990673b1a4dd9.js.gz application.css application.css.gz config/ database.yml
  9. 9. Deployment nginx ~/ict-ref-cloud/current/public/tmp/unicorn.ict-ref-cloud.sock unicorn ~/ict-ref-cloud/current
  10. 10. OWASP Top Ten Security Risk 1. Injection 2. Cross Site Scripting 3. Broken Authentication and Session Management 4. Insecure Direct Object Reference 5. Cross Site Request Forgery 6. Security Misconfiguration 7. Insecure Cryptographic Storage 8. Failure To Restrict URL Access 9. Insufficient Transport Layer Protection10. Unvalidated Redirects and Forwards
  11. 11. OWASP Top Ten Security Risk 1. Injection 2. Cross Site Scripting 3. Broken Authentication and Session Management 4. Insecure Direct Object Reference 5. Cross Site Request Forgery 6. Security Misconfiguration 7. Insecure Cryptographic Storage 8. Failure To Restrict URL Access 9. Insufficient Transport Layer Protection10. Unvalidated Redirects and Forwards Problems related specifically to view layer.
  12. 12. The Rails Way to security: CSRF protection XSS protection
  13. 13. Cross Site Request Forgery/app/controllers/application_controller.rbclass ApplicationController < ActionController::Base protect_from_forgeryend/app/views/layouts/application.html.erb<head> <%= csrf_meta_tags %></head><meta content="authenticity_token" name="csrf-param"><meta content="KklMulGyhEfVztqfpMn5nRYc7zv+tNYb3YovBwOhTic=" name="csrf-token">
  14. 14. Cross Site Scripting<div id="comments"> <% @post.comments.each do |comment| %> <div class="comment"> <h4><%= comment.author %> says:</h4> <p><%= comment.content %></p> </div> <% end %></div><%# Insecure! %><%= raw product.description %>
  15. 15. The Rails Way to routing: Non-Resourceful routes Resourceful routes SEO friendly URLs
  16. 16. Non-Resourceful Routesmatch products/:id => products#showGET /products/10post products => products#createPOST /productsnamespace :api do put products/:id => api/products#updateendPUT /api/products/10
  17. 17. Non-Resourceful Routesmatch photos/show => photos#show, :via => [:get, :post]match photos/:id => photos#show, :constraints => { :id => /[A-Z]d{5}/ }match "photos", :constraints => { :subdomain => "admin" }match "/stories/:name" => redirect("/posts/%{name}")match books/*section/:title => books#showroot :to => pages#main
  18. 18. Resourceful Routesresources :photosget /photos => photos#indexget /photos/new => photos#newpost /photos => photos#createget /photos/:id => photos#showget /photos/:id/edit => photos#editput /photos/:id => photo#updatedelete /photos/:id => photo#destroy
  19. 19. Resourceful Routesresource :profileget /profile/new => profiles#newpost /profile => profiles#createget /profile => profiles#showget /profile/edit => profiles#editput /profile => profile#updatedelete /profile => profile#destroy
  20. 20. Named Routes<%= link_to Profile, profile_path %>=> <a href="/profile">Profile</a><%= link_to Preview, @photo %>=> <a href="/photo/10">Preview</a>
  21. 21. SEO Friendy URLs <%= link_to product.name, product %> Will generate /products/14-foo-bar /products/14-foo-bar "/products/:id" => "products#show" { :id => "14-foo-bar" } class Product < ActiveRecord::Base def to_param "#{id}-#{name.parametrize}" end Product.find(params[:id]) end Will call to_i Product.find(14)Example from: http://www.codeschool.com/courses/rails-best-practices
  22. 22. The Rails Way to viewrendering: Response rendering Structuring Layouts AJAX
  23. 23. Response Rendering/app /app /controllers /views products_controller.rb /products users_controller.rb index.html.erb show.html.erb /users index.html.erb new.html.erb
  24. 24. Response Renderingclass UsersController < ApplicationController def new @user = User.new new.html.erb end def create @user = User.new(params[:user]) if @user.save redirect_to :action => :show show.html.erb else render :new new.html.erb end endend
  25. 25. Rendering Responserender :editrender :action => :editrender editrender edit.html.erbrender :template => products/editrender products/editrender :file => /path/to/filerender /path/to/file
  26. 26. Rendering Responserender :inline => <p><%= @comment.content %></p>render :text => OKrender :json => @productrender :xml => @productrender :js => "alert(Hello Rails);"render :status => 500render :status => :forbiddenrender :nothing => true, :status => :created
  27. 27. Content Negotiationrespond_to do |format| format.html format.json { render :json => @product } format.jsend
  28. 28. Content Negotiationclass ProductsController < ApplicationController respond_to :html, :json, :js def edit respond_with Product.find(params[:id]) end def update respond_with Product.update(params[:id], params[:product]) endend
  29. 29. Structuring Layout/app /views /layouts application.html.erb (default) users.html.erb (UsersController) public.html.erb (layout public)
  30. 30. Structuring Layout<!DOCTYPE html><head> <title>User <%= yield :title %></title></head><html> <body> <%= yield %> </body></html>
  31. 31. Structuring Layout<% content_for :title, @post.title %><div id="post"> <h2><%= @post.title %></h2> <div><%= @post.content %></div></div>
  32. 32. View Helpersmodule ApplicationHelper def title(title) content_for :title, title endend
  33. 33. View Helpers<% title @post.title %><div id="post"> <h2><%= @post.title %></h2> <div><%= @post.content %></div></div>
  34. 34. Partials/app /views /products _form.html.erb _product.html.erb index.html.erb edit.html.erb new.html.erb
  35. 35. Partials/app/views/products/_product.html.erb<div class="product"> <h2><%= product.name %></h2> <p><%= product.description %></p></div> Partial parameter
  36. 36. Partials<h1>Products</h1><% @products.each do |product| %> <% render products/product, :product => product %><% end %>
  37. 37. Partials<h1>Products</h1><% @products.each do |product| %> <% render product %><% end %>
  38. 38. Partials<h1>Products</h1><% render @products %>
  39. 39. Partials/app/views/products/_form.html.erb<%= form_for @user do |f| %> <div class="input"> <%= f.label :name %> <%= f.text_field :name %> </div> <div class="input"> <%= f.label :description %> <%= f.text_area :description %> </div> <div class="actions"> <%= f.submit %> </div><% end %>
  40. 40. Partials../products/new.html.erb ../products/edit.html.erb<h1>New Product</h1> <h1>Edit Product</h1><div id="form"> <div id="form"> <% render form %> <% render form %></div> </div>
  41. 41. AJAX/app/views/products/_form.html.erb<%= form_for @user, :remote => true do |f| %> <div class="input"> <%= f.label :name %> <%= f.text_field :name %> </div> <div class="input"> <%= f.label :description %> <%= f.text_area :description %> </div> <div class="actions"> <%= f.submit %> </div><% end %>
  42. 42. AJAX/app/controllers/products_controller.rbclass ProductsController < ApplicationController def create @product = Product.new(params[:product]) respond_to do |format| if @product.save format.html { redirect_to @product } else format.html { render :action => new } format.js end end endend
  43. 43. AJAX/app/views/products/create.js.erb$(#form).html("<%= escape_javascript(render form) %>");
  44. 44. AJAX/app/views/products/index.html.erb<%= link_to "Delete", product, method: :delete, remote: true %><a href="/products/1" data-method="delete" data-remote="true" rel="nofollow">Delete</a> (Rails is using unobtrusive javascript technique)/app/views/products/destroy.js.erb$("#<%= dom_id @product %>").fadeOut();
  45. 45. The Rails Way to caching: Basic Caching Memoization
  46. 46. Page Cachingclass ProductsController < ActionController caches_page :index def index @products = Product.all end def create expire_page :action => :index endendPage caching wont work with filters.
  47. 47. Action Cachingclass ProductsController < ActionController before_filter :authenticate_user! caches_action :index def index @products = Product.all end def create expire_action :action => :index endend
  48. 48. Fragment Caching<% cache do %> All available products: <% @products.each do |p| %> <%= link_to p.name, product_url(p) %> <% end %><% end %>expire_fragment( :controller => products, :action => recent, :action_suffix => all_products)
  49. 49. Sweepersclass ProductSweeper < ActionController::Caching::Sweeper observe Product def after_create(product) # Expire the index page now that we added a new product expire_page(:controller => products, :action => index) # Expire a fragment expire_fragment(all_available_products) endend
  50. 50. Conditional GET supportclass ProductsController < ApplicationController def show @product = Product.find(params[:id]) if stale?(:last_modified => @product.updated_at.utc, :etag => @product) respond_to do |format| # ... normal response processing end end endend
  51. 51. Memoizationclass City < ActiveRecord::Base attr_accesible :name, :zip, :lat, :lon def display_name @display_name ||= "#@zip #@name" endend
  52. 52. The Rails Way to solvetypical problems: N+1 Problem Fetching object in batches
  53. 53. N+1 Problemclass User def recent_followers self.followers.recent.collect do |f| f.user.name end endendSelect followers where user_id=1 Select user where id=2 Select user where id=3 Select user where id=4 Select user where id=5Source: http://www.codeschool.com/courses/rails-best-practices
  54. 54. N+1 Problemclass User def recent_followers self.followers.recent.includes(:user).collect do |f| f.user.name end endendSelect followers where user_id=1 Select users where user_id in (2,3,4,5)Bullet Gem:https://github.com/flyerhzm/bulletSource: http://www.codeschool.com/courses/rails-best-practices
  55. 55. Fetching objects in JavaList<Tweet> tweets = tweetDao.findAllForUser(user);for (Tweet tweet : tweets) { // ...}for (Tweet tweet : user.getTweets()) { // ...}
  56. 56. Fetching objects in RailsTweet.where(user: user).find_each do |tweet| # ...enduser.tweets.find_each(batch_size: 5000) do |tweet| # ...endBy default pulls batches of 1,000 at a time
  57. 57. Try Rails!
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×