SlideShare uma empresa Scribd logo
1 de 58
Baixar para ler offline
Rails Best Practices




Friday, August 31, 12
Why best practices?




Friday, August 31, 12
Why best practices?

        01 Maintainability




Friday, August 31, 12
Why best practices?

        01 Maintainability

        02 DRY code




Friday, August 31, 12
Why best practices?

        01 Maintainability

        02 DRY code

        03 Better delegation




Friday, August 31, 12
Why best practices?

        01 Maintainability

        02 DRY code

        03 Better delegation

        04 It just works




Friday, August 31, 12
Fat models, skinny controllers




Friday, August 31, 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




Friday, August 31, 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




Friday, August 31, 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 index
            @tweets = Tweet.search(params)
          end

       end



Friday, August 31, 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                                              end


Friday, August 31, 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                                              end


Friday, August 31, 12
Scope it out




Friday, August 31, 12
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




Friday, August 31, 12
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




Friday, August 31, 12
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




Friday, August 31, 12
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

      end




Friday, August 31, 12
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

      end




Friday, August 31, 12
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
                                                                       end




Friday, August 31, 12
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
                                                                       end




Friday, August 31, 12
SQL Injection




Friday, August 31, 12
SQL Injection

     User.where("name = #{params[:search]}")




Friday, August 31, 12
SQL Injection

     User.where("name = #{params[:search]}")




Friday, August 31, 12
SQL Injection

     User.where("name = #{params[:search]}")




      User.where("name = ?", "#{params[:search]}")




Friday, August 31, 12
SQL Injection

     User.where("name = #{params[:search]}")




      User.where("name = ?", "#{params[:search]}")




       User.where(:name => params[:search])




Friday, August 31, 12
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
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 too
Friday, August 31, 12
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 too
Friday, August 31, 12
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 too
Friday, August 31, 12
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 too
Friday, August 31, 12
N+1 Queries are not cool




Friday, August 31, 12
N+1 Queries are not cool

          def recent_followers
            self.followers.recent.collect {|f| f.user.name }.to_sentence
          end




Friday, August 31, 12
N+1 Queries are not cool

          def recent_followers
            self.followers.recent.collect {|f| f.user.name }.to_sentence
          end




Friday, August 31, 12
N+1 Queries are not cool

          def recent_followers
            self.followers.recent.collect {|f| f.user.name }.to_sentence
          end




Friday, August 31, 12
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
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 queries



Friday, August 31, 12
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 queries



Friday, August 31, 12
N+1 Queries are not cool




Friday, August 31, 12
N+1 Queries are not cool

          def recent_followers
            self.followers.recent.includes(:user).collect {|f| f.user.name }.to_sentence
          end




Friday, August 31, 12
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
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




Friday, August 31, 12
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




Friday, August 31, 12
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/bullet

Friday, August 31, 12
Counter cache FTW!




Friday, August 31, 12
Counter cache FTW!

         <%= pluralize @user.tweets.length, 'tweet' %>




Friday, August 31, 12
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




Friday, August 31, 12
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




Friday, August 31, 12
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
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




Friday, August 31, 12
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




Friday, August 31, 12
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




Friday, August 31, 12
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
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
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




Friday, August 31, 12
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




Friday, August 31, 12
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 => true




Friday, August 31, 12
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
                                                        end

Friday, August 31, 12
Rails Best Practices




Friday, August 31, 12

Mais conteúdo relacionado

Mais procurados

Using the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service ClientsUsing the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service ClientsSalesforce Developers
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupHenrik Engström
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingNatasha Murashev
 
Programming Server side with Sevlet
 Programming Server side with Sevlet  Programming Server side with Sevlet
Programming Server side with Sevlet backdoor
 
SDPHP Lightning Talk - Let's Talk Laravel
SDPHP Lightning Talk - Let's Talk LaravelSDPHP Lightning Talk - Let's Talk Laravel
SDPHP Lightning Talk - Let's Talk Laravelmarcusamoore
 
Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子Yasuko Ohba
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)Hendrik Ebbers
 
Ruby on Rails Security Updated (Rails 3) at RailsWayCon
Ruby on Rails Security Updated (Rails 3) at RailsWayConRuby on Rails Security Updated (Rails 3) at RailsWayCon
Ruby on Rails Security Updated (Rails 3) at RailsWayConheikowebers
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSVisual Engineering
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationSociable
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Managementstable|kernel
 
Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)Antonio Peric-Mazar
 
Lecture 3: Servlets - Session Management
Lecture 3:  Servlets - Session ManagementLecture 3:  Servlets - Session Management
Lecture 3: Servlets - Session ManagementFahad Golra
 
Refactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.jsRefactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.jsStacy London
 
Demystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsDemystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsMichael Miles
 
NYCCAMP 2015 Demystifying Drupal AJAX Callback Commands
NYCCAMP 2015 Demystifying Drupal AJAX Callback CommandsNYCCAMP 2015 Demystifying Drupal AJAX Callback Commands
NYCCAMP 2015 Demystifying Drupal AJAX Callback CommandsMichael Miles
 

Mais procurados (20)

Using the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service ClientsUsing the Tooling API to Generate Apex SOAP Web Service Clients
Using the Tooling API to Generate Apex SOAP Web Service Clients
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetup
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
 
Laravel tips-2019-04
Laravel tips-2019-04Laravel tips-2019-04
Laravel tips-2019-04
 
Programming Server side with Sevlet
 Programming Server side with Sevlet  Programming Server side with Sevlet
Programming Server side with Sevlet
 
SDPHP Lightning Talk - Let's Talk Laravel
SDPHP Lightning Talk - Let's Talk LaravelSDPHP Lightning Talk - Let's Talk Laravel
SDPHP Lightning Talk - Let's Talk Laravel
 
Day seven
Day sevenDay seven
Day seven
 
Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
 
Ruby on Rails Security Updated (Rails 3) at RailsWayCon
Ruby on Rails Security Updated (Rails 3) at RailsWayConRuby on Rails Security Updated (Rails 3) at RailsWayCon
Ruby on Rails Security Updated (Rails 3) at RailsWayCon
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentation
 
Workshop 17: EmberJS parte II
Workshop 17: EmberJS parte IIWorkshop 17: EmberJS parte II
Workshop 17: EmberJS parte II
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Management
 
Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)Drupal8 for Symfony Developers (PHP Day Verona 2017)
Drupal8 for Symfony Developers (PHP Day Verona 2017)
 
Lecture 3: Servlets - Session Management
Lecture 3:  Servlets - Session ManagementLecture 3:  Servlets - Session Management
Lecture 3: Servlets - Session Management
 
IoC with PHP
IoC with PHPIoC with PHP
IoC with PHP
 
Refactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.jsRefactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.js
 
Demystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsDemystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback Commands
 
NYCCAMP 2015 Demystifying Drupal AJAX Callback Commands
NYCCAMP 2015 Demystifying Drupal AJAX Callback CommandsNYCCAMP 2015 Demystifying Drupal AJAX Callback Commands
NYCCAMP 2015 Demystifying Drupal AJAX Callback Commands
 

Semelhante a Rails Best Practices

Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Plataformatec
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2pyjonromero
 
Coding With Confidence: Adding TDD to Your Toolset
Coding With Confidence: Adding TDD to Your ToolsetCoding With Confidence: Adding TDD to Your Toolset
Coding With Confidence: Adding TDD to Your ToolsetPatrick Reagan
 
RubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendallRubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendalltutorialsruby
 
RubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendallRubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendalltutorialsruby
 
Comparison of different access controls
Comparison of different access controlsComparison of different access controls
Comparison of different access controlsRashmi Nair
 
Rails best practices_slides
Rails best practices_slidesRails best practices_slides
Rails best practices_slidesCao Van An
 
Sentiment analysis- Modi, Trump, Putin
Sentiment analysis- Modi, Trump, PutinSentiment analysis- Modi, Trump, Putin
Sentiment analysis- Modi, Trump, PutinAhmed Zaidi
 
Simple restfull app_s
Simple restfull app_sSimple restfull app_s
Simple restfull app_snetwix
 
Rx 101 Codemotion Milan 2015 - Tamir Dresher
Rx 101   Codemotion Milan 2015 - Tamir DresherRx 101   Codemotion Milan 2015 - Tamir Dresher
Rx 101 Codemotion Milan 2015 - Tamir DresherTamir Dresher
 
Tamir Dresher - Reactive Extensions (Rx) 101
Tamir Dresher - Reactive Extensions (Rx) 101Tamir Dresher - Reactive Extensions (Rx) 101
Tamir Dresher - Reactive Extensions (Rx) 101Codemotion
 
Railsにコントリビュートしてきました
RailsにコントリビュートしてきましたRailsにコントリビュートしてきました
Railsにコントリビュートしてきましたよしだ あつし
 
Dynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java AnnotationsDynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java AnnotationsBroadleaf Commerce
 
Moving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domainMoving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domainPatrick Dougall
 
Android Cursor Utils - NYC Android Meetup
Android Cursor Utils - NYC Android MeetupAndroid Cursor Utils - NYC Android Meetup
Android Cursor Utils - NYC Android MeetupRon Shapiro
 
DJango admin interface
DJango admin interfaceDJango admin interface
DJango admin interfaceMahesh Shitole
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1Jano Suchal
 
Devoxx 2012 hibernate envers
Devoxx 2012   hibernate enversDevoxx 2012   hibernate envers
Devoxx 2012 hibernate enversRomain Linsolas
 

Semelhante a Rails Best Practices (20)

Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2py
 
Coding With Confidence: Adding TDD to Your Toolset
Coding With Confidence: Adding TDD to Your ToolsetCoding With Confidence: Adding TDD to Your Toolset
Coding With Confidence: Adding TDD to Your Toolset
 
RubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendallRubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendall
 
RubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendallRubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendall
 
Comparison of different access controls
Comparison of different access controlsComparison of different access controls
Comparison of different access controls
 
Rails best practices_slides
Rails best practices_slidesRails best practices_slides
Rails best practices_slides
 
Sentiment analysis- Modi, Trump, Putin
Sentiment analysis- Modi, Trump, PutinSentiment analysis- Modi, Trump, Putin
Sentiment analysis- Modi, Trump, Putin
 
Simple restfull app_s
Simple restfull app_sSimple restfull app_s
Simple restfull app_s
 
Rx 101 Codemotion Milan 2015 - Tamir Dresher
Rx 101   Codemotion Milan 2015 - Tamir DresherRx 101   Codemotion Milan 2015 - Tamir Dresher
Rx 101 Codemotion Milan 2015 - Tamir Dresher
 
Tamir Dresher - Reactive Extensions (Rx) 101
Tamir Dresher - Reactive Extensions (Rx) 101Tamir Dresher - Reactive Extensions (Rx) 101
Tamir Dresher - Reactive Extensions (Rx) 101
 
Struts 2
Struts 2Struts 2
Struts 2
 
Railsにコントリビュートしてきました
RailsにコントリビュートしてきましたRailsにコントリビュートしてきました
Railsにコントリビュートしてきました
 
Dynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java AnnotationsDynamically Generate a CRUD Admin Panel with Java Annotations
Dynamically Generate a CRUD Admin Panel with Java Annotations
 
Dsl
DslDsl
Dsl
 
Moving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domainMoving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domain
 
Android Cursor Utils - NYC Android Meetup
Android Cursor Utils - NYC Android MeetupAndroid Cursor Utils - NYC Android Meetup
Android Cursor Utils - NYC Android Meetup
 
DJango admin interface
DJango admin interfaceDJango admin interface
DJango admin interface
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
 
Devoxx 2012 hibernate envers
Devoxx 2012   hibernate enversDevoxx 2012   hibernate envers
Devoxx 2012 hibernate envers
 

Mais de Icalia Labs

Building an Api the Right Way
Building an Api the Right WayBuilding an Api the Right Way
Building an Api the Right WayIcalia Labs
 
Agile practices for management
Agile practices for managementAgile practices for management
Agile practices for managementIcalia Labs
 
Building something out of Nothing
Building something out of NothingBuilding something out of Nothing
Building something out of NothingIcalia Labs
 
Furatto tertulia
Furatto tertuliaFuratto tertulia
Furatto tertuliaIcalia Labs
 
Simple but Useful Design Principles.
Simple but Useful Design Principles.Simple but Useful Design Principles.
Simple but Useful Design Principles.Icalia Labs
 
Your time saving front end workflow
Your time saving front end workflowYour time saving front end workflow
Your time saving front end workflowIcalia Labs
 
Customer Experience Basics
Customer Experience BasicsCustomer Experience Basics
Customer Experience BasicsIcalia Labs
 
Introduction to Swift programming language.
Introduction to Swift programming language.Introduction to Swift programming language.
Introduction to Swift programming language.Icalia Labs
 
Time Hacks for Work
Time Hacks for WorkTime Hacks for Work
Time Hacks for WorkIcalia Labs
 
Culture in a team
Culture in a teamCulture in a team
Culture in a teamIcalia Labs
 
Presentacion vim
Presentacion vimPresentacion vim
Presentacion vimIcalia Labs
 
Using github development process in your company
Using github development process in your companyUsing github development process in your company
Using github development process in your companyIcalia Labs
 
The Art of Pitching
The Art of PitchingThe Art of Pitching
The Art of PitchingIcalia Labs
 
Introduccion meteor.js
Introduccion meteor.jsIntroduccion meteor.js
Introduccion meteor.jsIcalia Labs
 

Mais de Icalia Labs (16)

Building an Api the Right Way
Building an Api the Right WayBuilding an Api the Right Way
Building an Api the Right Way
 
Agile practices for management
Agile practices for managementAgile practices for management
Agile practices for management
 
Building something out of Nothing
Building something out of NothingBuilding something out of Nothing
Building something out of Nothing
 
Furatto tertulia
Furatto tertuliaFuratto tertulia
Furatto tertulia
 
Simple but Useful Design Principles.
Simple but Useful Design Principles.Simple but Useful Design Principles.
Simple but Useful Design Principles.
 
Your time saving front end workflow
Your time saving front end workflowYour time saving front end workflow
Your time saving front end workflow
 
Customer Experience Basics
Customer Experience BasicsCustomer Experience Basics
Customer Experience Basics
 
Introduction to Swift programming language.
Introduction to Swift programming language.Introduction to Swift programming language.
Introduction to Swift programming language.
 
Time Hacks for Work
Time Hacks for WorkTime Hacks for Work
Time Hacks for Work
 
Culture in a team
Culture in a teamCulture in a team
Culture in a team
 
Curso rails
Curso railsCurso rails
Curso rails
 
Presentacion vim
Presentacion vimPresentacion vim
Presentacion vim
 
Using github development process in your company
Using github development process in your companyUsing github development process in your company
Using github development process in your company
 
The Art of Pitching
The Art of PitchingThe Art of Pitching
The Art of Pitching
 
Introduccion meteor.js
Introduccion meteor.jsIntroduccion meteor.js
Introduccion meteor.js
 
Rspec and Rails
Rspec and RailsRspec and Rails
Rspec and Rails
 

Último

"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 

Último (20)

"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 

Rails Best Practices

  • 3. Why best practices? 01 Maintainability Friday, August 31, 12
  • 4. Why best practices? 01 Maintainability 02 DRY code Friday, August 31, 12
  • 5. Why best practices? 01 Maintainability 02 DRY code 03 Better delegation Friday, August 31, 12
  • 6. Why best practices? 01 Maintainability 02 DRY code 03 Better delegation 04 It just works Friday, August 31, 12
  • 7. Fat models, skinny controllers Friday, 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 end Friday, 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 end Friday, 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 end Friday, 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 end Friday, 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 end Friday, August 31, 12
  • 13. Scope it out Friday, 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 end Friday, 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 end Friday, 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 end Friday, 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 end Friday, 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 end Friday, 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 end Friday, 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 end Friday, 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 too Friday, 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 too Friday, 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 too Friday, 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 too Friday, August 31, 12
  • 31. N+1 Queries are not cool Friday, August 31, 12
  • 32. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence end Friday, August 31, 12
  • 33. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence end Friday, August 31, 12
  • 34. N+1 Queries are not cool def recent_followers self.followers.recent.collect {|f| f.user.name }.to_sentence end Friday, 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 queries Friday, 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 queries Friday, August 31, 12
  • 38. N+1 Queries are not cool Friday, 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 end Friday, 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 = 1 Friday, 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 queries Friday, 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/bullet Friday, 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 array Friday, 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 array Friday, 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 tweets Friday, 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 tweets Friday, 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 tweets Friday, 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 user Friday, 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 user Friday, 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 => true Friday, 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 end Friday, August 31, 12