Rails Best Practices
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Rails Best Practices

on

  • 1,690 views

 

Statistics

Views

Total Views
1,690
Views on SlideShare
1,687
Embed Views
3

Actions

Likes
3
Downloads
30
Comments
0

2 Embeds 3

https://twitter.com 2
https://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Rails Best Practices Presentation Transcript

  • 1. Rails Best PracticesFriday, August 31, 12
  • 2. Why best practices?Friday, August 31, 12
  • 3. Why best practices? 01 MaintainabilityFriday, August 31, 12
  • 4. Why best practices? 01 Maintainability 02 DRY codeFriday, August 31, 12
  • 5. Why best practices? 01 Maintainability 02 DRY code 03 Better delegationFriday, August 31, 12
  • 6. Why best practices? 01 Maintainability 02 DRY code 03 Better delegation 04 It just worksFriday, August 31, 12
  • 7. Fat models, skinny controllersFriday, August 31, 12
  • 8. Fat models, skinny controllers class TweetsController < ApplicationController def index if params[:search].present? @tweets = Tweet.all else @tweets = Tweet.where("content LIKE ?", "%#{params[:search]}%") end end endFriday, August 31, 12
  • 9. Fat models, skinny controllers class TweetsController < ApplicationController def index if params[:search].present? @tweets = Tweet.all else @tweets = Tweet.where("content LIKE ?", "%#{params[:search]}%") end end endFriday, August 31, 12
  • 10. Fat models, skinny controllers class TweetsController < ApplicationController def index if params[:search].present? @tweets = Tweet.all else @tweets = Tweet.where("content LIKE ?", "%#{params[:search]}%") end end end class TweetsController < ApplicationController def index @tweets = Tweet.search(params) end endFriday, August 31, 12
  • 11. Fat models, skinny controllers class TweetsController < ApplicationController def index if params[:search].present? @tweets = Tweet.all else @tweets = Tweet.where("content LIKE ?", "%#{params[:search]}%") end end end class TweetsController < ApplicationController def self.search(params= {}) if params[:search].present def index where("content LIKE ?", "%#{params[:search]}%") @tweets = Tweet.search(params) else end all end end endFriday, August 31, 12
  • 12. Fat models, skinny controllers class TweetsController < ApplicationController def index if params[:search].present? @tweets = Tweet.all else @tweets = Tweet.where("content LIKE ?", "%#{params[:search]}%") end end end class TweetsController < ApplicationController def self.search(params= {}) if params[:search].present def index where("content LIKE ?", "%#{params[:search]}%") @tweets = Tweet.search(params) else end all end end endFriday, August 31, 12
  • 13. Scope it outFriday, August 31, 12
  • 14. Scope it out class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.where("retweets_count > 5").order(created_at DESC).limit(5) end endFriday, August 31, 12
  • 15. Scope it out class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.where("retweets_count > 5").order(created_at DESC).limit(5) end endFriday, August 31, 12
  • 16. Scope it out class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.where("retweets_count > 5").order(created_at DESC).limit(5) end endFriday, August 31, 12
  • 17. Scope it out class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.where("retweets_count > 5").order(created_at DESC).limit(5) end end class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.with_many_retweets.recent.limit(5) end endFriday, August 31, 12
  • 18. Scope it out class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.where("retweets_count > 5").order(created_at DESC).limit(5) end end class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.with_many_retweets.recent.limit(5) end endFriday, August 31, 12
  • 19. Scope it out class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.where("retweets_count > 5").order(created_at DESC).limit(5) end end class Tweet < ActiveRecord::Base class UsersController < ApplicationController attr_accessible :content, :user_id def show belongs_to :user @user = User.find(params[:id]) @tweets = @user.tweets.with_many_retweets.recent.limit(5) scope :recent, order(created_at DESC) end scope :with_many_retweets, where("retweets_count > 5") end endFriday, August 31, 12
  • 20. Scope it out class UsersController < ApplicationController def show @user = User.find(params[:id]) @tweets = @user.tweets.where("retweets_count > 5").order(created_at DESC).limit(5) end end class Tweet < ActiveRecord::Base class UsersController < ApplicationController attr_accessible :content, :user_id def show belongs_to :user @user = User.find(params[:id]) @tweets = @user.tweets.with_many_retweets.recent.limit(5) scope :recent, order(created_at DESC) end scope :with_many_retweets, where("retweets_count > 5") end endFriday, August 31, 12
  • 21. SQL InjectionFriday, August 31, 12
  • 22. SQL Injection User.where("name = #{params[:search]}")Friday, August 31, 12
  • 23. SQL Injection User.where("name = #{params[:search]}")Friday, August 31, 12
  • 24. SQL Injection User.where("name = #{params[:search]}") User.where("name = ?", "#{params[:search]}")Friday, August 31, 12
  • 25. SQL Injection User.where("name = #{params[:search]}") User.where("name = ?", "#{params[:search]}") User.where(:name => params[:search])Friday, August 31, 12
  • 26. SQL Injection User.where("name = #{params[:search]}") User.where("name = ?", "#{params[:search]}") User.where(:name => params[:search]) User.where("username = :login OR email = :login", {:login => params[:login]})Friday, August 31, 12
  • 27. Model without DB && REST #encoding: utf-8 class ContactsController < ApplicationController class Contact def new include ActiveModel::Validations @contact = Contact.new include ActiveModel::Conversion end attr_accessor :name, :email, :message def create validates :name, :email, :company, :reason, @contact = Contact.new(params[:contact]) :message, :presence => true if @contact.valid? ContactMailer.contact_message(@contact).deliver def initialize(attributes = {}) redirect_to root_path, :notice => "Sweet!" attributes.each do |name, value| else send("#{name}=", value) render :new end end end end end def persisted? false end end REST: Don’t be too deep - /users/1/tweets/ 3/comments/2 Not using REST is ok tooFriday, August 31, 12
  • 28. Model without DB && REST #encoding: utf-8 class ContactsController < ApplicationController class Contact def new include ActiveModel::Validations @contact = Contact.new include ActiveModel::Conversion end attr_accessor :name, :email, :message def create validates :name, :email, :company, :reason, @contact = Contact.new(params[:contact]) :message, :presence => true if @contact.valid? ContactMailer.contact_message(@contact).deliver def initialize(attributes = {}) redirect_to root_path, :notice => "Sweet!" attributes.each do |name, value| else send("#{name}=", value) render :new end end end end end def persisted? false end end REST: Don’t be too deep - /users/1/tweets/ 3/comments/2 Not using REST is ok tooFriday, August 31, 12
  • 29. Model without DB && REST #encoding: utf-8 class ContactsController < ApplicationController class Contact def new include ActiveModel::Validations @contact = Contact.new include ActiveModel::Conversion end attr_accessor :name, :email, :message def create validates :name, :email, :company, :reason, @contact = Contact.new(params[:contact]) :message, :presence => true if @contact.valid? ContactMailer.contact_message(@contact).deliver def initialize(attributes = {}) redirect_to root_path, :notice => "Sweet!" attributes.each do |name, value| else send("#{name}=", value) render :new end end end end end def persisted? false end end REST: Don’t be too deep - /users/1/tweets/ 3/comments/2 Not using REST is ok tooFriday, August 31, 12
  • 30. Model without DB && REST #encoding: utf-8 class ContactsController < ApplicationController class Contact def new include ActiveModel::Validations @contact = Contact.new include ActiveModel::Conversion end attr_accessor :name, :email, :message def create validates :name, :email, :company, :reason, @contact = Contact.new(params[:contact]) :message, :presence => true if @contact.valid? ContactMailer.contact_message(@contact).deliver def initialize(attributes = {}) redirect_to root_path, :notice => "Sweet!" attributes.each do |name, value| else send("#{name}=", value) render :new end end end end end def persisted? false end end REST: Don’t be too deep - /users/1/tweets/ 3/comments/2 Not using REST is ok tooFriday, August 31, 12
  • 31. N+1 Queries are not coolFriday, August 31, 12
  • 32. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence endFriday, August 31, 12
  • 33. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence endFriday, August 31, 12
  • 34. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence endFriday, August 31, 12
  • 35. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence end => “Edo, Lentes, Javi”Friday, August 31, 12
  • 36. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence end => “Edo, Lentes, Javi” Select followers where user_id = 1 Select user where id=2 Select user where id=3 Select user where id=4 Select user where id=5 5 fat queriesFriday, August 31, 12
  • 37. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence end => “Edo, Lentes, Javi” Select followers where user_id = 1 Select user where id=2 Select user where id=3 Select user where id=4 Select user where id=5 5 fat queriesFriday, August 31, 12
  • 38. N+1 Queries are not coolFriday, August 31, 12
  • 39. N+1 Queries are not cool def recent_followers self.followers.recent.includes(:user).collect {|f| f.user.name }.to_sentence endFriday, August 31, 12
  • 40. N+1 Queries are not cool def recent_followers self.followers.recent.includes(:user).collect {|f| f.user.name }.to_sentence end => “Edo, Lentes, Javi”Friday, August 31, 12
  • 41. N+1 Queries are not cool def recent_followers self.followers.recent.includes(:user).collect {|f| f.user.name }.to_sentence end => “Edo, Lentes, Javi” Select followers where user_id = 1Friday, August 31, 12
  • 42. N+1 Queries are not cool def recent_followers self.followers.recent.includes(:user).collect {|f| f.user.name }.to_sentence end => “Edo, Lentes, Javi” Select followers where user_id = 1 Select users where user_id in (2,3,4,5) 2 queriesFriday, August 31, 12
  • 43. N+1 Queries are not cool def recent_followers self.followers.recent.includes(:user).collect {|f| f.user.name }.to_sentence end => “Edo, Lentes, Javi” Select followers where user_id = 1 Select users where user_id in (2,3,4,5) 2 queries Check out the bullet gem at: h"ps://github.com/flyerhzm/bulletFriday, August 31, 12
  • 44. Counter cache FTW!Friday, August 31, 12
  • 45. Counter cache FTW! <%= pluralize @user.tweets.length, tweet %>Friday, August 31, 12
  • 46. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the arrayFriday, August 31, 12
  • 47. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the arrayFriday, August 31, 12
  • 48. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %>Friday, August 31, 12
  • 49. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweetsFriday, August 31, 12
  • 50. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweetsFriday, August 31, 12
  • 51. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweetsFriday, August 31, 12
  • 52. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweets <%= pluralize @user.tweets.size, tweet %>Friday, August 31, 12
  • 53. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweets <%= pluralize @user.tweets.size, tweet %>Friday, August 31, 12
  • 54. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweets <%= pluralize @user.tweets.size, tweet %> 1. Select all tweets from userFriday, August 31, 12
  • 55. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweets <%= pluralize @user.tweets.size, tweet %> 1. Select all tweets from userFriday, August 31, 12
  • 56. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweets <%= pluralize @user.tweets.size, tweet %> 1. Select all tweets from user belongs_to :user, :counter_cache => trueFriday, August 31, 12
  • 57. Counter cache FTW! 1. Select all tweets from user <%= pluralize @user.tweets.length, tweet %> 2. Populate an array of objects 3. Call length on the array <%= pluralize @user.tweets.count, tweet %> 1. Select all tweets from user 2. Do count query for tweets <%= pluralize @user.tweets.size, tweet %> 1. Select all tweets from user def self.up belongs_to :user, :counter_cache => true add_column :users, :tweets_count, :integer, :default => 0 end def self.down remove_column :users, :tweets_count endFriday, August 31, 12
  • 58. Rails Best PracticesFriday, August 31, 12