SlideShare a Scribd company logo
1 of 65
Ror lab. season 2
 - the 6th round -


Active Record
Validations

 September 15th, 2012

   Hyoseong Choi
     ROR Lab.
Contents
      Validations                         Callbacks
•   The Object Life Cycle          •   Callbacks Overview
•   Validations Overview           •   Available Callbacks
•   Validation Helpers             •   Running Callbacks
•   Common Validation              •   Skipping Callbacks
    Options                        •   Halting Execution
•   Conditional Validation         •   Relational Callbacks
•   Custom Validations             •   Conditional Callbacks
•   Working with Validation        •   Callback Classes
    Errors
                                   •   Observers
•   Displaying Validation Errors
                                   •   Transaction Callbacks
    in the View

                                                       ROR Lab.
Validation Levels

• Native DB constraints - DB-dependent
• Client-side validations - javascript ?
• Controller-level validations - keep skinny
• Model-level validations - the best way

                                       ROR Lab.
“new” method
• A new object instantiated      vs. persisted?

• not yet to store to database : new_record?
• no validation called, but ...



                                             ROR Lab.
Validation Time Point
                             ActiveRecord
               Web Server

                Model              DB
                Validation
                   save
                  create
                  update
  clients
         Model-level validations


                                   ROR Lab.
Validation Event
        Triggering validations                   Skipping validations
        •   .create                              •   .decrement!
        •   .create!                             •   #decrement_counter
        •   .save                                •   .increment!
        •   .save!                               •   #increment_counter
        •   #update                              •   .toggle!
        •   .update_attributes                   •   .touch
        •   .update_attributes!                  •   #update_all
                                                 •   .update_attribute deprecated
                                                 •   .update_column
                                                 •   #update_counters



Ref.:   ActiveRecord::Persistence   ActiveRecord::CounterCache
                                                                      ROR Lab.
Call Validations
• valid? or invalid?




                       ROR Lab.
valid? vs Errors




By definition,
an object is valid if this collection is empty
after running validations.

                                                 ROR Lab.
Validation Helpers
• acceptance     • validates_associated
• confirmation    • validates_each
• exclusion      • validates_with
• format
• inclusion           :on
                            • save(default)
                            • create
• length                    • update

• numericality     :message
• presence
• uniqueness
                                  ROR Lab.
Common Options

:allow_nil - nil
:allow_blank - nil or whitespace
:message - overriding default error message
:on - :create / :update / :save



                                     ROR Lab.
Conditional Validation
  :if and :unless

    • A Symbol : a method name
    • A String : a really short condition
    • A Proc : an inline condition
  Grouping conditions : with_options

                                        ROR Lab.
Custom Validations
 • Custom validators modules
   : inherited from Two
      ★ ActiveModel::Validator
      ★ ActiveModel::EachValidator
      ★ Get the “record” argument as a
        parameter
 •   Custom validation methods
 •   Custom validation helpers

                                     ROR Lab.
Working with
  Validation Errors
• errors
• errors.messages
• errors.full_messages( or errors.to_a)
• errors[:attr] : for a specific attribute
• errors.add(:attr, message)(or errors[:attr]=)
• errors[:base] : object’s state as a whole
• errors.clear : intentionally to clear
• errors.size : count of errors
                                         ROR Lab.
Displaying Validation
 Errors in the View
★ gem ‘dynamic_form’   ★ Error   Messages CSS

                         .field_with_errors
                         #errorExplanation
                         #errorExplanation h2
                         #errorExplanation p
                         #errorExplanation ul li




                                      ROR Lab.
Validation Errors :                                                https://github.com/joelmoss/dynamic_form




                                                                 Error CSS
                                                                                               #error_explanation

                                                                                                                          #error_explanation h2
                                                                                                             #error_explanation p
<%= form_for(@product) do |f| %>

 <% if @product.errors.any? %>
  <div id="error_explanation">                                                                   #error_explanation ul li
   <h2><%= pluralize(@product.errors.count, "error") %>
      prohibited this product from being saved:
   </h2>
   <ul>
   <% @product.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
   <% end %>
   </ul>
  </div>
 <% end %>                                                                                                 .field_with_errors




                                                                                                          generated by scaffold

                                                          apps/assets/stylesheets/scaffolds.css.scss
                                                                                                                                ROR Lab.
Validation Errors :                          https://github.com/joelmoss/dynamic_form




                     Error CSS
                                                   #error_explanation
       <%= form_for(@product) do |f| %>
                                                                              #error_explanation h2
        <% if @product.errors.any? %>                            #error_explanation p
         <div id="error_explanation">
          <h2><%= pluralize(@product.errors.count, "error") %>
                                                  #error_explanation ul li
             prohibited this product from being saved:
          </h2>
          <ul>
          <% @product.errors.full_messages.each do |msg| %>
           <li><%= msg %></li>                            .field_with_errors
          <% end %>
          </ul>
         </div>
        <% end %>


                                                              generated by scaffold

              apps/assets/stylesheets/scaffolds.css.scss
                                                                                    ROR Lab.
Validation Errors :              https://github.com/joelmoss/dynamic_form




                                Error CSS
apps/assets
/stylesheets
/scaffolds.css.scss                        #error_explanation

.field_with_errors {                                                   #error_explanation h2
  padding: 2px;
  background-color: red;                                 #error_explanation p
  display: table;
}

#error_explanation {                        #error_explanation ul li
 width: 450px;
 border: 2px solid red;
 padding: 7px;
 padding-bottom: 0;
 margin-bottom: 20px;
 background-color: #f0f0f0;
 h2 {                                                  .field_with_errors
   text-align: left;
   font-weight: bold;
   padding: 5px 5px 5px 15px;
   font-size: 12px;
   margin: -7px;
   margin-bottom: 0px;
   background-color: #c00;
   color: #fff;
 }
 ul li {
                                                      generated by scaffold
   font-size: 12px;
   list-style: square;



                                                                           ROR Lab.
Validation Errors :


       ‘dynamic_form’
   • f.error_messages or
   • error_messages_for :product

   <%= form_for(@product) do |f| %>

    <%= f.error_messages %>

   <% end %>




                                      ROR Lab.
Validation Errors :                          https://github.com/joelmoss/dynamic_form




                 ‘dynamic_form’

                                                           generated by dynamic_form
        r_ tag
       e
:h ead                         :header_message
                                             :message




            <%= f.error_messages
              :header_message => "Invalid product!",
              :message => "You'll need to fix the following fields:",
              :header_tag => :h3 %>



                                                                                          ROR Lab.
Validation Errors :                           https://github.com/joelmoss/dynamic_form




                Error HTML
 config/initializers/custom_error_message_html.rb                              field object

 ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
   errors = Array(instance.error_message).join(',')
   unless html_tag =~ /^<label/
    %(#{html_tag}<span class="validation-error">&nbsp;#{errors}</span>).html_safe
   else
   %(#{html_tag}).html_safe
  end
 end




                               #{html_tag}            .validation-error




                                                                                     ROR Lab.
Validation Errors :                                                    https://github.com/joelmoss/dynamic_form




                    Error HTML
      <% if @product.errors.any? %>
       <div id="error_explanation">
        <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>
       </div>
      <% end %>




                                                                                                              ROR Lab.
감사합니다.
 
appendix
 
Active Record
 Counter Cache

• #decrement_counter
• #increment_counter   skipping
• #reset_counters      validations

• #update_counters
                               ROR Lab.
decrement vs
 decrement!




               ROR Lab.
toggle vs
 toggle!




            ROR Lab.
touch




        ROR Lab.
#update_all




              ROR Lab.
.update_column




             ROR Lab.
#update




          ROR Lab.
Validation Helpers :


               acceptance
     • a checkbox : a real or virtual attribute
     • “must be accepted”
     class Person  ActiveRecord::Base
       validates :terms_of_service, :acceptance = true



     class Person  ActiveRecord::Base
       validates :terms_of_service,
              :acceptance = { :accept = 'yes' }




                                                          ROR Lab.
Validation Helpers :


validates_associated
    • should if associated with other models
    • “is invalid”
     class Library  ActiveRecord::Base
       has_many :books
       validates_associated :books




    • should use on one end of your
       associations

                                          ROR Lab.
Validation Helpers :


           confirmation
    • a virtual attribute appended with
      “_confirmation”
    • “doesn’t match confirmation”
     class Person  ActiveRecord::Base
       validates :email, :confirmation = true
       validates :email_confirmation, :presence = true



     %= text_field :person, :email %
     %= text_field :person, :email_confirmation %



                                                         ROR Lab.
Validation Helpers :


                   exclusion
    • not included in a given set
      :any enumerable object
    • “is reserved”
     class Account  ActiveRecord::Base
       validates :subdomain,
         :exclusion = {
         :in = %w(www us ca jp),
         :message = Subdomain %{value} is reserved. }




                                                           ROR Lab.
Validation Helpers :


                       format
    • match a given regular expression
    • “is invalid”

     class Product  ActiveRecord::Base
       validates :legacy_code,
              :format = { :with = /A[a-zA-Z]+z/,
              :message = Only letters allowed }




                                                       ROR Lab.
Validation Helpers :


                   inclusion
    • included in a given set
      : any enumerable object
    • “is not included in the list”
     class Coffee  ActiveRecord::Base
       validates :size,
           :inclusion = {
             :in = %w(small medium large),
          :message = %{value} is not a valid size
         }




                                                       ROR Lab.
Validation Helpers :


                         length                        (1/2)

   • length constraint options
      - :minimum, :maximum, :in/:within, :is
      - a placeholder - %{count}

  class Person  ActiveRecord::Base
    validates :name, :length = { :minimum = 2 }
    validates :bio, :length = { :maximum = 500 }
    validates :password, :length = { :in = 6..20 }
    validates :registration_number, :length = { :is = 6 }




                                                               ROR Lab.
Validation Helpers :


                        length                     (2/2)

   • options
     - :wrong_length, :too_long, :too_short
     - a placeholder - %{count}
   class Essay  ActiveRecord::Base
     validates :content, :size = {
       :minimum   = 300,
       :maximum   = 400,
       :tokenizer = lambda { |str| str.scan(/w+/) },
       :too_short = must have at least %{count} words,
       :too_long  = must have at most %{count} words
     }




                                                            ROR Lab.
Validation Helpers :


            numericality                                 (1/2)

    • only numeric values
      : (+/−) integer/floating point
    • “is not a number”
     class Person  ActiveRecord::Base
       validates :email, :confirmation = true
       validates :email_confirmation, :presence = true



     %= text_field :person, :email %
     %= text_field :person, :email_confirmation %



                                                         ROR Lab.
Validation Helpers :


               numericality                                                          (2/2)


     class Player  ActiveRecord::Base
       validates :points, :numericality = true
       validates :games_played,
            :numericality = { :only_integer = true }

                                                                   /A[+−]?d+Z/



   •:greater_than               ➡   “must   be   greater than %{count}”
   •:greater_than_or_equal_to   ➡   “must   be   greater than or equal to %{count}
   •:equal_to                   ➡   “must   be   equal to %{count}”
   •:less_than                  ➡   “must   be   less than %{count}”
   •:less_than_or_equal_to      ➡   “must   be   less than or equal to %{count}
   •:odd                        ➡   “must   be   odd”
   •:even                       ➡   “must   be   even”




                                                                                     ROR Lab.
Validation Helpers :


                   presence (1/2)
   • empty or whitespaces
   • “can’t be empty”
    class Person  ActiveRecord::Base
      validates :name, :login, :email, :presence = true
    end




    class LineItem  ActiveRecord::Base
      belongs_to :order
      validates :order_id, :presence = true



                                                           ROR Lab.
Validation Helpers :


                     presence (2/2)
   • empty or whitespaces
   • “can’t be empty”

                                               ✘
    class Person  ActiveRecord::Base
      validates :is_admin, :presence = true
    end              a boolean field ➞ false.blank? is true


    class Person  ActiveRecord::Base
      validates :is_admin,
             :inclusion = { :in = [true, false] }



                                                             ROR Lab.
Validation Helpers :


               uniqueness
   • add_index :table_name, :column_name, unique = true
   • “has already been taken”
    class Account  ActiveRecord::Base
      validates :email, :uniqueness = true                  other
    end                                                    attributes
    class Holiday  ActiveRecord::Base
      validates :name, :uniqueness = { :scope = :year,
        :message = should happen once per year }
    end
    class Person  ActiveRecord::Base
      validates :name,
           :uniqueness = { :case_sensitive = false }


                                                                ROR Lab.
Validation Helpers :


         validates_with (1/2)
   • a separate class for validation
   • no default validate error message
    class Person  ActiveRecord::Base
      validates_with GoodnessValidator,[:if/:unless/:on]
    end
     
    class GoodnessValidator  ActiveModel::Validator
      def validate(record)
        if record.first_name == Evil
          record.errors[:base]  This person is evil
        end
      end



                                                           ROR Lab.
Validation Helpers :


            validates_with (2/2)
   • any additional options ➞ options
  class Person  ActiveRecord::Base
    validates_with GoodnessValidator, :fields =
                            [:first_name, :last_name]
  end
   
  class GoodnessValidator  ActiveModel::Validator
    def validate(record)
      if options[:fields].any?{|field| record.send(field) == Evil }
        record.errors[:base]  This person is evil
      end
    end
  end




                                                                     ROR Lab.
Validation Helpers :


                   validates_each
            • no predefined validation function
               ➞a block
            • no default error message
class Person  ActiveRecord::Base
  validates_each :name, :surname do |record, attr, value|
    record.errors.add(attr, 'must start with upper case') if value =~ /A[a-z]/
  end
end




                                                                                  ROR Lab.
Common Validation Options :


                  :allow_nil

    class Coffee  ActiveRecord::Base
      validates :size,
        :inclusion = { :in = %w(small medium large),
        :message = %{value} is not a valid size },
        :allow_nil = true




                                                         ROR Lab.
Common Validation Options :


            :allow_blank
    • nil or an empty string
    class Topic  ActiveRecord::Base
      validates :title,
             :length = { :is = 5 },
             :allow_blank = true
    end
     
    Topic.create(title = ).valid?  # = true




                                                    ROR Lab.
Common Validation Options :


                                      :on
          • when the validation should happen
class Person  ActiveRecord::Base
  # it will be possible to update email with a duplicated value
  validates :email, :uniqueness = true, :on = :create
 
  # it will be possible to create the record with a non-numerical age
  validates :age, :numericality = true, :on = :update
 
  # the default (validates on both create and update)
  validates :name, :presence = true, :on = :save




                                                                        ROR Lab.
Conditional Validation


             :if  :unless                         (1/4)

    • Using a Symbol : a method name
    class Order  ActiveRecord::Base
      validates :card_number, :presence = true,
             :if = :paid_with_card?
     
      def paid_with_card?
        payment_type == card
      end




                                                    ROR Lab.
Conditional Validation


             :if  :unless                     (2/4)

    • Using a String : a really short condition
    class Person  ActiveRecord::Base
      validates :surname, :presence = true,
             :if = name.nil?




                                                ROR Lab.
Conditional Validation


              :if  :unless                             (3/4)

    • Using a Proc : an inline condition
    class Account  ActiveRecord::Base
      validates :password, :confirmation = true,
        :unless = Proc.new { |a| a.password.blank? }
                                    a model
                                     object




                                                         ROR Lab.
Conditional Validation


              :if  :unless                                (4/4)

    • grouping conditional validations
                                             condition
                                              object
   class User  ActiveRecord::Base
     with_options :if = :is_admin? do |admin|
       admin.validates :password, :length = { :minimum = 10 }
       admin.validates :email, :presence = true
     end




                                                              ROR Lab.
Custom Validations :


   Custom Validators (1/2)
   • to extend ActiveMode::Validator
   • to validate the state of whole record
   class MyValidator  ActiveModel::Validator
     def validate(record)
       unless record.name.starts_with? 'X'
         record.errors[:name]  'Need a name starting with X please!'
       end
     end
   end
    
   class Person
     include ActiveModel::Validations
     validates_with MyValidator
   end




                                                                         ROR Lab.
Custom Validations :


   Custom Validators (2/2)
   • to extend ActiveMode::EachValidator
   • to validate individual attributes
  class EmailValidator  ActiveModel::EachValidator
    def validate_each(record, attribute, value)
      unless value =~ /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})z/i
        record.errors[attribute]  (options[:message] || is not an email)
      end
    end
  end
                                                     EmailValidator
  class Person  ActiveRecord::Base
    validates :email, :presence = true, :email = true
  end




                                                                               ROR Lab.
Custom Validations :


     Custom Methods (1/2)
   • to verify the state of models
  class Invoice  ActiveRecord::Base
    validate :expiration_date_cannot_be_in_the_past,
      :discount_cannot_be_greater_than_total_value
   
    def expiration_date_cannot_be_in_the_past
      if !expiration_date.blank? and expiration_date  Date.today
        errors.add(:expiration_date, can't be in the past)
      end
    end                                                         EmailValidator
   
    def discount_cannot_be_greater_than_total_value
      if discount  total_value
        errors.add(:discount, can't be greater than total value)
      end
    end
  end



                                                                                 ROR Lab.
Custom Validations :


     Custom Methods (2/2)
   • to verify the state of models
  class Invoice  ActiveRecord::Base
    validate :active_customer, :on = :create
   
    def active_customer
      errors.add(:customer_id, is not active)
                        unless customer.active?
    end




                                                  ROR Lab.
Custom Validations :


       Custom Helpers
   • to reuse in several different models
   • to put in config/initializers
  ActiveRecord::Base.class_eval do
    def self.validates_as_choice(attr_name, n, options={})
      validates attr_name,
        :inclusion = { { :in = 1..n }.merge!(options) }
    end
  end



   class Movie  ActiveRecord::Base
     validates_as_choice :rating, 5
   end


                                                             ROR Lab.
Validation Errors :


                                errors
   • an instance of ActiveModel::Errors
   • key : attribute name
       value : an array of strings with all errors
   class Person  ActiveRecord::Base
     validates :name, :presence = true, :length = { :minimum = 3 }
   end
    
   person = Person.new
   person.valid? # = false
   person.errors
    # = {:name =
          [can't be blank, is too short (minimum is 3 characters)]}
    
   person = Person.new(:name = John Doe)
   person.valid? # = true
   person.errors # = []



                                                                          ROR Lab.
Validation Errors :


                            errors[ ]
   • to check the error message of a specific
       attribute
   class Person  ActiveRecord::Base
     validates :name, :presence = true, :length = { :minimum = 3 }
   end
    
   person = Person.new(:name = John Doe)
   person.valid? # = true
   person.errors[:name] # = []
    
   person = Person.new(:name = JD)
   person.valid? # = false
   person.errors[:name] # = [is too short (minimum is 3 characters)]
    
   person = Person.new
   person.valid? # = false
   person.errors[:name]
    # = [can't be blank, is too short (minimum is 3 characters)]




                                                                          ROR Lab.
Validation Errors :


                     errors.add                                         (1/2)

   • to manually add messages of a specific
      attribute
   class Person  ActiveRecord::Base
     def a_method_used_for_validation_purposes
       errors.add(:name, cannot contain the characters !@#%*()_-+=)
     end
   end
    
   person = Person.create(:name = !@#)
    
   person.errors[:name]
    # = [cannot contain the characters !@#%*()_-+=]
    
   person.errors.full_messages
    # = [Name cannot contain the characters !@#%*()_-+=]




                                                                          ROR Lab.
Validation Errors :


                    errors.add                                        (2/2)

                                  -or-
   class Person  ActiveRecord::Base
     def a_method_used_for_validation_purposes
       errors[:name] = cannot contain the characters !@#%*()_-+=)
     end
   end
    
   person = Person.create(:name = !@#)
    
   person.errors[:name]
    # = [cannot contain the characters !@#%*()_-+=]
    
   person.errors.to_a
    # = [Name cannot contain the characters !@#%*()_-+=]




                                                                        ROR Lab.
Validation Errors :


              errors[:base]
   • related to the object’s state as a whole
   • an array
   class Person  ActiveRecord::Base
     def a_method_used_for_validation_purposes
       errors[:base]  This person is invalid because ...
     end
   end




                                                               ROR Lab.

More Related Content

Viewers also liked

ActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsPaul Gallagher
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsSerge Smetana
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on RailsAgnieszka Figiel
 
Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Technologies
 
Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and RailsWen-Tien Chang
 
From a monolithic Ruby on Rails app to the JVM
From a monolithic  Ruby on Rails app  to the JVMFrom a monolithic  Ruby on Rails app  to the JVM
From a monolithic Ruby on Rails app to the JVMPhil Calçado
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails IntroductionThomas Fuchs
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017John Maeda
 

Viewers also liked (10)

ActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails Applications
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
 
Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and Rails
 
Ruby Beyond Rails
Ruby Beyond RailsRuby Beyond Rails
Ruby Beyond Rails
 
From a monolithic Ruby on Rails app to the JVM
From a monolithic  Ruby on Rails app  to the JVMFrom a monolithic  Ruby on Rails app  to the JVM
From a monolithic Ruby on Rails app to the JVM
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails Introduction
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017
 

Similar to ActiveRecord Validations, Season 2

Ruby On Rails Pitfalls
Ruby On Rails PitfallsRuby On Rails Pitfalls
Ruby On Rails PitfallsRobin Lu
 
Continuous Integration For Rails Project
Continuous Integration For Rails ProjectContinuous Integration For Rails Project
Continuous Integration For Rails ProjectLouie Zhao
 
Frozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code SmellsFrozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code SmellsDennis Ushakov
 
Debugging WordPress
Debugging WordPressDebugging WordPress
Debugging WordPressMario Peshev
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on RailsMark Menard
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js FundamentalsMark
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperfNew Relic
 
Action Controller Overview, Season 1
Action Controller Overview, Season 1Action Controller Overview, Season 1
Action Controller Overview, Season 1RORLAB
 
Here Be Dragons - Debugging WordPress
Here Be Dragons - Debugging WordPressHere Be Dragons - Debugging WordPress
Here Be Dragons - Debugging WordPressRami Sayar
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialYi-Ting Cheng
 
Lessons learned from a huge Rails app - RubyConf Brasil 2019
Lessons learned from a huge Rails app - RubyConf Brasil 2019Lessons learned from a huge Rails app - RubyConf Brasil 2019
Lessons learned from a huge Rails app - RubyConf Brasil 2019Nahuel Garbezza
 
Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015Andrew Krug
 
ruby on rails pitfalls
ruby on rails pitfallsruby on rails pitfalls
ruby on rails pitfallsRobbin Fan
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-publicChul Ju Hong
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatternsChul Ju Hong
 
Iac :: Lessons Learned from Dev to Ops
Iac :: Lessons Learned from Dev to OpsIac :: Lessons Learned from Dev to Ops
Iac :: Lessons Learned from Dev to OpsEmma Button
 
Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1RORLAB
 
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu Código
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu CódigoWhere Does the Fat Goes? Utilizando Form Objects Para Simplificar seu Código
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu CódigoGuilherme
 
td_mxc_rubyrails_shin
td_mxc_rubyrails_shintd_mxc_rubyrails_shin
td_mxc_rubyrails_shintutorialsruby
 

Similar to ActiveRecord Validations, Season 2 (20)

Ruby On Rails Pitfalls
Ruby On Rails PitfallsRuby On Rails Pitfalls
Ruby On Rails Pitfalls
 
Continuous Integration For Rails Project
Continuous Integration For Rails ProjectContinuous Integration For Rails Project
Continuous Integration For Rails Project
 
Frozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code SmellsFrozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code Smells
 
Debugging WordPress
Debugging WordPressDebugging WordPress
Debugging WordPress
 
Active Model
Active ModelActive Model
Active Model
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on Rails
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js Fundamentals
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
 
Action Controller Overview, Season 1
Action Controller Overview, Season 1Action Controller Overview, Season 1
Action Controller Overview, Season 1
 
Here Be Dragons - Debugging WordPress
Here Be Dragons - Debugging WordPressHere Be Dragons - Debugging WordPress
Here Be Dragons - Debugging WordPress
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Lessons learned from a huge Rails app - RubyConf Brasil 2019
Lessons learned from a huge Rails app - RubyConf Brasil 2019Lessons learned from a huge Rails app - RubyConf Brasil 2019
Lessons learned from a huge Rails app - RubyConf Brasil 2019
 
Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015Selenium Tips & Tricks - StarWest 2015
Selenium Tips & Tricks - StarWest 2015
 
ruby on rails pitfalls
ruby on rails pitfallsruby on rails pitfalls
ruby on rails pitfalls
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-public
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatterns
 
Iac :: Lessons Learned from Dev to Ops
Iac :: Lessons Learned from Dev to OpsIac :: Lessons Learned from Dev to Ops
Iac :: Lessons Learned from Dev to Ops
 
Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1
 
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu Código
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu CódigoWhere Does the Fat Goes? Utilizando Form Objects Para Simplificar seu Código
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu Código
 
td_mxc_rubyrails_shin
td_mxc_rubyrails_shintd_mxc_rubyrails_shin
td_mxc_rubyrails_shin
 

More from RORLAB

Getting Started with Rails (4)
Getting Started with Rails (4) Getting Started with Rails (4)
Getting Started with Rails (4) RORLAB
 
Getting Started with Rails (3)
Getting Started with Rails (3) Getting Started with Rails (3)
Getting Started with Rails (3) RORLAB
 
Getting Started with Rails (2)
Getting Started with Rails (2)Getting Started with Rails (2)
Getting Started with Rails (2)RORLAB
 
Getting Started with Rails (1)
Getting Started with Rails (1)Getting Started with Rails (1)
Getting Started with Rails (1)RORLAB
 
Self join in active record association
Self join in active record associationSelf join in active record association
Self join in active record associationRORLAB
 
Asset Pipeline in Ruby on Rails
Asset Pipeline in Ruby on RailsAsset Pipeline in Ruby on Rails
Asset Pipeline in Ruby on RailsRORLAB
 
레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개
레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개
레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개RORLAB
 
Active Support Core Extension (3)
Active Support Core Extension (3)Active Support Core Extension (3)
Active Support Core Extension (3)RORLAB
 
Active Support Core Extension (2)
Active Support Core Extension (2)Active Support Core Extension (2)
Active Support Core Extension (2)RORLAB
 
Active Support Core Extensions (1)
Active Support Core Extensions (1)Active Support Core Extensions (1)
Active Support Core Extensions (1)RORLAB
 
Action Controller Overview, Season 2
Action Controller Overview, Season 2Action Controller Overview, Season 2
Action Controller Overview, Season 2RORLAB
 
Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2RORLAB
 
Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2RORLAB
 
Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2RORLAB
 
ActiveRecord Query Interface (2), Season 2
ActiveRecord Query Interface (2), Season 2ActiveRecord Query Interface (2), Season 2
ActiveRecord Query Interface (2), Season 2RORLAB
 
Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2RORLAB
 
Active Record Association (2), Season 2
Active Record Association (2), Season 2Active Record Association (2), Season 2
Active Record Association (2), Season 2RORLAB
 
ActiveRecord Association (1), Season 2
ActiveRecord Association (1), Season 2ActiveRecord Association (1), Season 2
ActiveRecord Association (1), Season 2RORLAB
 
ActiveRecord Callbacks & Observers, Season 2
ActiveRecord Callbacks & Observers, Season 2ActiveRecord Callbacks & Observers, Season 2
ActiveRecord Callbacks & Observers, Season 2RORLAB
 
Rails Database Migration, Season 2
Rails Database Migration, Season 2Rails Database Migration, Season 2
Rails Database Migration, Season 2RORLAB
 

More from RORLAB (20)

Getting Started with Rails (4)
Getting Started with Rails (4) Getting Started with Rails (4)
Getting Started with Rails (4)
 
Getting Started with Rails (3)
Getting Started with Rails (3) Getting Started with Rails (3)
Getting Started with Rails (3)
 
Getting Started with Rails (2)
Getting Started with Rails (2)Getting Started with Rails (2)
Getting Started with Rails (2)
 
Getting Started with Rails (1)
Getting Started with Rails (1)Getting Started with Rails (1)
Getting Started with Rails (1)
 
Self join in active record association
Self join in active record associationSelf join in active record association
Self join in active record association
 
Asset Pipeline in Ruby on Rails
Asset Pipeline in Ruby on RailsAsset Pipeline in Ruby on Rails
Asset Pipeline in Ruby on Rails
 
레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개
레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개
레일스가이드 한글번역 공개프로젝트 RORLabGuides 소개
 
Active Support Core Extension (3)
Active Support Core Extension (3)Active Support Core Extension (3)
Active Support Core Extension (3)
 
Active Support Core Extension (2)
Active Support Core Extension (2)Active Support Core Extension (2)
Active Support Core Extension (2)
 
Active Support Core Extensions (1)
Active Support Core Extensions (1)Active Support Core Extensions (1)
Active Support Core Extensions (1)
 
Action Controller Overview, Season 2
Action Controller Overview, Season 2Action Controller Overview, Season 2
Action Controller Overview, Season 2
 
Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2
 
Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2
 
Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2
 
ActiveRecord Query Interface (2), Season 2
ActiveRecord Query Interface (2), Season 2ActiveRecord Query Interface (2), Season 2
ActiveRecord Query Interface (2), Season 2
 
Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2Active Record Query Interface (1), Season 2
Active Record Query Interface (1), Season 2
 
Active Record Association (2), Season 2
Active Record Association (2), Season 2Active Record Association (2), Season 2
Active Record Association (2), Season 2
 
ActiveRecord Association (1), Season 2
ActiveRecord Association (1), Season 2ActiveRecord Association (1), Season 2
ActiveRecord Association (1), Season 2
 
ActiveRecord Callbacks & Observers, Season 2
ActiveRecord Callbacks & Observers, Season 2ActiveRecord Callbacks & Observers, Season 2
ActiveRecord Callbacks & Observers, Season 2
 
Rails Database Migration, Season 2
Rails Database Migration, Season 2Rails Database Migration, Season 2
Rails Database Migration, Season 2
 

Recently uploaded

Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
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...Drew Madelung
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
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 Nanonetsnaman860154
 
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 productivityPrincipled Technologies
 
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 interpreternaman860154
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 

Recently uploaded (20)

Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
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...
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
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
 
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
 
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
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 

ActiveRecord Validations, Season 2

  • 1. Ror lab. season 2 - the 6th round - Active Record Validations September 15th, 2012 Hyoseong Choi ROR Lab.
  • 2. Contents Validations Callbacks • The Object Life Cycle • Callbacks Overview • Validations Overview • Available Callbacks • Validation Helpers • Running Callbacks • Common Validation • Skipping Callbacks Options • Halting Execution • Conditional Validation • Relational Callbacks • Custom Validations • Conditional Callbacks • Working with Validation • Callback Classes Errors • Observers • Displaying Validation Errors • Transaction Callbacks in the View ROR Lab.
  • 3. Validation Levels • Native DB constraints - DB-dependent • Client-side validations - javascript ? • Controller-level validations - keep skinny • Model-level validations - the best way ROR Lab.
  • 4. “new” method • A new object instantiated vs. persisted? • not yet to store to database : new_record? • no validation called, but ... ROR Lab.
  • 5. Validation Time Point ActiveRecord Web Server Model DB Validation save create update clients Model-level validations ROR Lab.
  • 6. Validation Event Triggering validations Skipping validations • .create • .decrement! • .create! • #decrement_counter • .save • .increment! • .save! • #increment_counter • #update • .toggle! • .update_attributes • .touch • .update_attributes! • #update_all • .update_attribute deprecated • .update_column • #update_counters Ref.: ActiveRecord::Persistence ActiveRecord::CounterCache ROR Lab.
  • 7. Call Validations • valid? or invalid? ROR Lab.
  • 8. valid? vs Errors By definition, an object is valid if this collection is empty after running validations. ROR Lab.
  • 9. Validation Helpers • acceptance • validates_associated • confirmation • validates_each • exclusion • validates_with • format • inclusion :on • save(default) • create • length • update • numericality :message • presence • uniqueness ROR Lab.
  • 10. Common Options :allow_nil - nil :allow_blank - nil or whitespace :message - overriding default error message :on - :create / :update / :save ROR Lab.
  • 11. Conditional Validation :if and :unless • A Symbol : a method name • A String : a really short condition • A Proc : an inline condition Grouping conditions : with_options ROR Lab.
  • 12. Custom Validations • Custom validators modules : inherited from Two ★ ActiveModel::Validator ★ ActiveModel::EachValidator ★ Get the “record” argument as a parameter • Custom validation methods • Custom validation helpers ROR Lab.
  • 13. Working with Validation Errors • errors • errors.messages • errors.full_messages( or errors.to_a) • errors[:attr] : for a specific attribute • errors.add(:attr, message)(or errors[:attr]=) • errors[:base] : object’s state as a whole • errors.clear : intentionally to clear • errors.size : count of errors ROR Lab.
  • 14. Displaying Validation Errors in the View ★ gem ‘dynamic_form’ ★ Error Messages CSS .field_with_errors #errorExplanation #errorExplanation h2 #errorExplanation p #errorExplanation ul li ROR Lab.
  • 15. Validation Errors : https://github.com/joelmoss/dynamic_form Error CSS #error_explanation #error_explanation h2 #error_explanation p <%= form_for(@product) do |f| %> <% if @product.errors.any? %> <div id="error_explanation"> #error_explanation ul li <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved: </h2> <ul> <% @product.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> .field_with_errors generated by scaffold apps/assets/stylesheets/scaffolds.css.scss ROR Lab.
  • 16. Validation Errors : https://github.com/joelmoss/dynamic_form Error CSS #error_explanation <%= form_for(@product) do |f| %> #error_explanation h2 <% if @product.errors.any? %> #error_explanation p <div id="error_explanation"> <h2><%= pluralize(@product.errors.count, "error") %> #error_explanation ul li prohibited this product from being saved: </h2> <ul> <% @product.errors.full_messages.each do |msg| %> <li><%= msg %></li> .field_with_errors <% end %> </ul> </div> <% end %> generated by scaffold apps/assets/stylesheets/scaffolds.css.scss ROR Lab.
  • 17. Validation Errors : https://github.com/joelmoss/dynamic_form Error CSS apps/assets /stylesheets /scaffolds.css.scss #error_explanation .field_with_errors { #error_explanation h2 padding: 2px; background-color: red; #error_explanation p display: table; } #error_explanation { #error_explanation ul li width: 450px; border: 2px solid red; padding: 7px; padding-bottom: 0; margin-bottom: 20px; background-color: #f0f0f0; h2 { .field_with_errors text-align: left; font-weight: bold; padding: 5px 5px 5px 15px; font-size: 12px; margin: -7px; margin-bottom: 0px; background-color: #c00; color: #fff; } ul li { generated by scaffold font-size: 12px; list-style: square; ROR Lab.
  • 18. Validation Errors : ‘dynamic_form’ • f.error_messages or • error_messages_for :product <%= form_for(@product) do |f| %> <%= f.error_messages %> <% end %> ROR Lab.
  • 19. Validation Errors : https://github.com/joelmoss/dynamic_form ‘dynamic_form’ generated by dynamic_form r_ tag e :h ead :header_message :message <%= f.error_messages :header_message => "Invalid product!",   :message => "You'll need to fix the following fields:",   :header_tag => :h3 %> ROR Lab.
  • 20. Validation Errors : https://github.com/joelmoss/dynamic_form Error HTML config/initializers/custom_error_message_html.rb field object ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|   errors = Array(instance.error_message).join(',') unless html_tag =~ /^<label/    %(#{html_tag}<span class="validation-error">&nbsp;#{errors}</span>).html_safe else %(#{html_tag}).html_safe end end #{html_tag} .validation-error ROR Lab.
  • 21. Validation Errors : https://github.com/joelmoss/dynamic_form Error HTML <% if @product.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2> </div> <% end %> ROR Lab.
  • 23.  
  • 25.  
  • 26. Active Record Counter Cache • #decrement_counter • #increment_counter skipping • #reset_counters validations • #update_counters ROR Lab.
  • 28. toggle vs toggle! ROR Lab.
  • 29. touch ROR Lab.
  • 30. #update_all ROR Lab.
  • 31. .update_column ROR Lab.
  • 32. #update ROR Lab.
  • 33. Validation Helpers : acceptance • a checkbox : a real or virtual attribute • “must be accepted” class Person ActiveRecord::Base   validates :terms_of_service, :acceptance = true class Person ActiveRecord::Base   validates :terms_of_service, :acceptance = { :accept = 'yes' } ROR Lab.
  • 34. Validation Helpers : validates_associated • should if associated with other models • “is invalid” class Library ActiveRecord::Base   has_many :books   validates_associated :books • should use on one end of your associations ROR Lab.
  • 35. Validation Helpers : confirmation • a virtual attribute appended with “_confirmation” • “doesn’t match confirmation” class Person ActiveRecord::Base   validates :email, :confirmation = true   validates :email_confirmation, :presence = true %= text_field :person, :email % %= text_field :person, :email_confirmation % ROR Lab.
  • 36. Validation Helpers : exclusion • not included in a given set :any enumerable object • “is reserved” class Account ActiveRecord::Base   validates :subdomain, :exclusion = { :in = %w(www us ca jp),     :message = Subdomain %{value} is reserved. } ROR Lab.
  • 37. Validation Helpers : format • match a given regular expression • “is invalid” class Product ActiveRecord::Base   validates :legacy_code, :format = { :with = /A[a-zA-Z]+z/,      :message = Only letters allowed } ROR Lab.
  • 38. Validation Helpers : inclusion • included in a given set : any enumerable object • “is not included in the list” class Coffee ActiveRecord::Base   validates :size, :inclusion = { :in = %w(small medium large),      :message = %{value} is not a valid size } ROR Lab.
  • 39. Validation Helpers : length (1/2) • length constraint options - :minimum, :maximum, :in/:within, :is - a placeholder - %{count} class Person ActiveRecord::Base   validates :name, :length = { :minimum = 2 }   validates :bio, :length = { :maximum = 500 }   validates :password, :length = { :in = 6..20 }   validates :registration_number, :length = { :is = 6 } ROR Lab.
  • 40. Validation Helpers : length (2/2) • options - :wrong_length, :too_long, :too_short - a placeholder - %{count} class Essay ActiveRecord::Base   validates :content, :size = {     :minimum   = 300,     :maximum   = 400,     :tokenizer = lambda { |str| str.scan(/w+/) },     :too_short = must have at least %{count} words,     :too_long  = must have at most %{count} words   } ROR Lab.
  • 41. Validation Helpers : numericality (1/2) • only numeric values : (+/−) integer/floating point • “is not a number” class Person ActiveRecord::Base   validates :email, :confirmation = true   validates :email_confirmation, :presence = true %= text_field :person, :email % %= text_field :person, :email_confirmation % ROR Lab.
  • 42. Validation Helpers : numericality (2/2) class Player ActiveRecord::Base   validates :points, :numericality = true   validates :games_played, :numericality = { :only_integer = true } /A[+−]?d+Z/ •:greater_than ➡ “must be greater than %{count}” •:greater_than_or_equal_to ➡ “must be greater than or equal to %{count} •:equal_to ➡ “must be equal to %{count}” •:less_than ➡ “must be less than %{count}” •:less_than_or_equal_to ➡ “must be less than or equal to %{count} •:odd ➡ “must be odd” •:even ➡ “must be even” ROR Lab.
  • 43. Validation Helpers : presence (1/2) • empty or whitespaces • “can’t be empty” class Person ActiveRecord::Base   validates :name, :login, :email, :presence = true end class LineItem ActiveRecord::Base   belongs_to :order   validates :order_id, :presence = true ROR Lab.
  • 44. Validation Helpers : presence (2/2) • empty or whitespaces • “can’t be empty” ✘ class Person ActiveRecord::Base   validates :is_admin, :presence = true end a boolean field ➞ false.blank? is true class Person ActiveRecord::Base   validates :is_admin, :inclusion = { :in = [true, false] } ROR Lab.
  • 45. Validation Helpers : uniqueness • add_index :table_name, :column_name, unique = true • “has already been taken” class Account ActiveRecord::Base   validates :email, :uniqueness = true other end attributes class Holiday ActiveRecord::Base   validates :name, :uniqueness = { :scope = :year,     :message = should happen once per year } end class Person ActiveRecord::Base   validates :name, :uniqueness = { :case_sensitive = false } ROR Lab.
  • 46. Validation Helpers : validates_with (1/2) • a separate class for validation • no default validate error message class Person ActiveRecord::Base   validates_with GoodnessValidator,[:if/:unless/:on] end   class GoodnessValidator ActiveModel::Validator   def validate(record)     if record.first_name == Evil       record.errors[:base] This person is evil     end   end ROR Lab.
  • 47. Validation Helpers : validates_with (2/2) • any additional options ➞ options class Person ActiveRecord::Base   validates_with GoodnessValidator, :fields = [:first_name, :last_name] end   class GoodnessValidator ActiveModel::Validator   def validate(record)     if options[:fields].any?{|field| record.send(field) == Evil }       record.errors[:base] This person is evil     end   end end ROR Lab.
  • 48. Validation Helpers : validates_each • no predefined validation function ➞a block • no default error message class Person ActiveRecord::Base   validates_each :name, :surname do |record, attr, value|     record.errors.add(attr, 'must start with upper case') if value =~ /A[a-z]/   end end ROR Lab.
  • 49. Common Validation Options : :allow_nil class Coffee ActiveRecord::Base   validates :size, :inclusion = { :in = %w(small medium large),     :message = %{value} is not a valid size }, :allow_nil = true ROR Lab.
  • 50. Common Validation Options : :allow_blank • nil or an empty string class Topic ActiveRecord::Base   validates :title, :length = { :is = 5 }, :allow_blank = true end   Topic.create(title = ).valid?  # = true ROR Lab.
  • 51. Common Validation Options : :on • when the validation should happen class Person ActiveRecord::Base   # it will be possible to update email with a duplicated value   validates :email, :uniqueness = true, :on = :create     # it will be possible to create the record with a non-numerical age   validates :age, :numericality = true, :on = :update     # the default (validates on both create and update)   validates :name, :presence = true, :on = :save ROR Lab.
  • 52. Conditional Validation :if :unless (1/4) • Using a Symbol : a method name class Order ActiveRecord::Base   validates :card_number, :presence = true, :if = :paid_with_card?     def paid_with_card?     payment_type == card   end ROR Lab.
  • 53. Conditional Validation :if :unless (2/4) • Using a String : a really short condition class Person ActiveRecord::Base   validates :surname, :presence = true, :if = name.nil? ROR Lab.
  • 54. Conditional Validation :if :unless (3/4) • Using a Proc : an inline condition class Account ActiveRecord::Base   validates :password, :confirmation = true,     :unless = Proc.new { |a| a.password.blank? } a model object ROR Lab.
  • 55. Conditional Validation :if :unless (4/4) • grouping conditional validations condition object class User ActiveRecord::Base   with_options :if = :is_admin? do |admin|     admin.validates :password, :length = { :minimum = 10 }     admin.validates :email, :presence = true   end ROR Lab.
  • 56. Custom Validations : Custom Validators (1/2) • to extend ActiveMode::Validator • to validate the state of whole record class MyValidator ActiveModel::Validator   def validate(record)     unless record.name.starts_with? 'X'       record.errors[:name] 'Need a name starting with X please!'     end   end end   class Person   include ActiveModel::Validations   validates_with MyValidator end ROR Lab.
  • 57. Custom Validations : Custom Validators (2/2) • to extend ActiveMode::EachValidator • to validate individual attributes class EmailValidator ActiveModel::EachValidator   def validate_each(record, attribute, value)     unless value =~ /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})z/i       record.errors[attribute] (options[:message] || is not an email)     end   end end   EmailValidator class Person ActiveRecord::Base   validates :email, :presence = true, :email = true end ROR Lab.
  • 58. Custom Validations : Custom Methods (1/2) • to verify the state of models class Invoice ActiveRecord::Base   validate :expiration_date_cannot_be_in_the_past,     :discount_cannot_be_greater_than_total_value     def expiration_date_cannot_be_in_the_past     if !expiration_date.blank? and expiration_date Date.today       errors.add(:expiration_date, can't be in the past)     end   end EmailValidator     def discount_cannot_be_greater_than_total_value     if discount total_value       errors.add(:discount, can't be greater than total value)     end   end end ROR Lab.
  • 59. Custom Validations : Custom Methods (2/2) • to verify the state of models class Invoice ActiveRecord::Base   validate :active_customer, :on = :create     def active_customer     errors.add(:customer_id, is not active) unless customer.active?   end ROR Lab.
  • 60. Custom Validations : Custom Helpers • to reuse in several different models • to put in config/initializers ActiveRecord::Base.class_eval do   def self.validates_as_choice(attr_name, n, options={})     validates attr_name, :inclusion = { { :in = 1..n }.merge!(options) }   end end class Movie ActiveRecord::Base   validates_as_choice :rating, 5 end ROR Lab.
  • 61. Validation Errors : errors • an instance of ActiveModel::Errors • key : attribute name value : an array of strings with all errors class Person ActiveRecord::Base   validates :name, :presence = true, :length = { :minimum = 3 } end   person = Person.new person.valid? # = false person.errors  # = {:name = [can't be blank, is too short (minimum is 3 characters)]}   person = Person.new(:name = John Doe) person.valid? # = true person.errors # = [] ROR Lab.
  • 62. Validation Errors : errors[ ] • to check the error message of a specific attribute class Person ActiveRecord::Base   validates :name, :presence = true, :length = { :minimum = 3 } end   person = Person.new(:name = John Doe) person.valid? # = true person.errors[:name] # = []   person = Person.new(:name = JD) person.valid? # = false person.errors[:name] # = [is too short (minimum is 3 characters)]   person = Person.new person.valid? # = false person.errors[:name]  # = [can't be blank, is too short (minimum is 3 characters)] ROR Lab.
  • 63. Validation Errors : errors.add (1/2) • to manually add messages of a specific attribute class Person ActiveRecord::Base   def a_method_used_for_validation_purposes     errors.add(:name, cannot contain the characters !@#%*()_-+=)   end end   person = Person.create(:name = !@#)   person.errors[:name]  # = [cannot contain the characters !@#%*()_-+=]   person.errors.full_messages  # = [Name cannot contain the characters !@#%*()_-+=] ROR Lab.
  • 64. Validation Errors : errors.add (2/2) -or- class Person ActiveRecord::Base   def a_method_used_for_validation_purposes     errors[:name] = cannot contain the characters !@#%*()_-+=)   end end   person = Person.create(:name = !@#)   person.errors[:name]  # = [cannot contain the characters !@#%*()_-+=]   person.errors.to_a  # = [Name cannot contain the characters !@#%*()_-+=] ROR Lab.
  • 65. Validation Errors : errors[:base] • related to the object’s state as a whole • an array class Person ActiveRecord::Base   def a_method_used_for_validation_purposes     errors[:base] This person is invalid because ...   end end ROR Lab.
  • 66. Validation Errors : errors.clear • related to the object’s state as a whole • an array class Person ActiveRecord::Base   validates :name, :presence = true, :length = { :minimum = 3 } end   person = Person.new person.valid? # = false person.errors[:name]  # = [can't be blank, is too short (minimum is 3 characters)]   person.errors.clear person.errors.empty? # = true   p.save # = false   p.errors[:name]  # = [can't be blank, is too short (minimum is 3 characters)] ROR Lab.
  • 67. Validation Errors : errors.size class Person ActiveRecord::Base   validates :name, :presence = true, :length = { :minimum = 3 } end   person = Person.new person.valid? # = false person.errors.size # = 2   person = Person.new(:name = Andrea, :email = andrea@example.com) person.valid? # = true person.errors.size # = 0 ROR Lab.

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n