Your SlideShare is downloading. ×
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Rails Best Practices
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Rails Best Practices

1,751

Published on

Published in: Technology, Business
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,751
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
79
Comments
0
Likes
4
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

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

×