SlideShare une entreprise Scribd logo
1  sur  58
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

Programming Server side with Sevlet
 Programming Server side with Sevlet  Programming Server side with Sevlet
Programming Server side with Sevlet
backdoor
 
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
heikowebers
 

Tendances (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
 

Similaire à Rails Best Practices

RubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendallRubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendall
tutorialsruby
 
RubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendallRubyOnRails-Cheatsheet-BlaineKendall
RubyOnRails-Cheatsheet-BlaineKendall
tutorialsruby
 
Rails best practices_slides
Rails best practices_slidesRails best practices_slides
Rails best practices_slides
Cao Van An
 
Simple restfull app_s
Simple restfull app_sSimple restfull app_s
Simple restfull app_s
netwix
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
Jano Suchal
 

Similaire à 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
 
Tamir Dresher - Reactive Extensions (Rx) 101
Tamir Dresher - Reactive Extensions (Rx) 101Tamir Dresher - Reactive Extensions (Rx) 101
Tamir Dresher - Reactive Extensions (Rx) 101
 
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
 
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
 

Plus de Icalia Labs

Presentacion vim
Presentacion vimPresentacion vim
Presentacion vim
Icalia Labs
 
The Art of Pitching
The Art of PitchingThe Art of Pitching
The Art of Pitching
Icalia Labs
 
Introduccion meteor.js
Introduccion meteor.jsIntroduccion meteor.js
Introduccion meteor.js
Icalia Labs
 

Plus 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
 

Dernier

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Dernier (20)

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

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