<commit_before>h2. Active Record Validations and Callbacks

This guide teaches you how to hook into the lifecycle of your Active Record objects. More precisely, you will learn how to validate the state of your objects before they go into the database as well as how to perform custom operations at certain points in the object lifecycle.

After reading this guide and trying out the presented concepts, we hope that you'll be able to:

* Use the built-in Active Record validation helpers
* Create your own custom validation methods
* Work with the error messages generated by the validation process
* Create callback methods to respond to events in the object lifecycle.
* Create special classes that encapsulate common behavior for your callbacks
* Create Rails Observers

endprologue.

h3. Overview of ActiveRecord Validation

Before you dive into the detail of validations in Rails, you should understand a bit about how validations fit into the big picture. Why should you use validations? When do these validations take place?

h4. Why Use ActiveRecord Validations?

The main reason for validating your objects before they get into the database is to ensure that only valid data is recorded. It's important to be sure that an email address column only contains valid email addresses, or that the customer's name column will never be empty. Constraints like that keep your database organized and helps your application to work properly. 

There are several ways that you could validate the data that goes to the database, including native database constraints, client-side validations, and model-level validations. Each of these has pros and cons:

* Using database constraints and/or stored procedures makes the validation mechanisms database-dependent and may turn your application into a hard to test and maintain beast. However, if your database is used by other applications, it may be a good idea to use some constraints also at the database level. Additionally, database-level validations can safely handle some things (such as uniqueness in heavily-used tables) that are problematic to implement from the application level.
* Implementing validations only at the client side can be difficult in web-based applications. Usually this kind of validation is done using javascript, which may be turned off in the user's browser, leading to invalid data getting inside your database. However, if combined with server side validation, client side validation may be useful, since the user can have a faster feedback from the application when trying to save invalid data.
* Using validation directly in your Active Record classes ensures that only valid data gets recorded, while still keeping the validation code in the right place, avoiding breaking the MVC pattern. Since the validation happens on the server side, the user cannot disable it, so it's also safer. It may be a hard and tedious work to implement some of the logic involved in your models' validations, but fear not: Active Record gives you the ability to easily create validations, providing built-in helpers for common validations while still allowing you to create your own validation methods.

h4. When Does Validation Happen?

There are two kinds of Active Record objects: those that correspond to a row inside your database and those that do not. When you create a fresh object, using the +new+ method, that object does not belong to the database yet. Once you call +save+ upon that object it will be saved into the appropriate database table. Active Record uses the +new_record?+ instance method to determine whether an object is already in the database or not. Consider the following simple Active Record class:

<ruby>
class Person < ActiveRecord::Base
end
</ruby>

We can see how it works by looking at some script/console output:

<shell>
>> p = Person.new(:name => "<NAME>", :birthdate => Date.parse("09/03/1979"))
=> #<Person id: nil, name: "<NAME>", birthdate: "1979-09-03", created_at: nil, updated_at: nil>
>> p.new_record?
=> true
>> p.save
=> true
>> p.new_record?
=> false
</shell>

Saving new records means sending an SQL +INSERT+ operation to the database, while saving existing records (by calling either +save+ or +update_attributes+) will result in a SQL +UPDATE+ operation. Active Record will use these facts to perform validations upon your objects, keeping them out of the database if their inner state is invalid in some way. You can specify validations that will be beformed every time a object is saved, just when you're creating a new record or when you're updating an existing one.

CAUTION: There are four methods that when called will trigger validation: +save+, +save!+, +update_attributes+ and +update_attributes!+. There is one update method for Active Record objects left, which is +update_attribute+. This method will update the value of an attribute _without_ triggering any validation. Be careful when using +update_attribute+, because it can let you save your objects in an invalid state.<commit_msg>Update Guides, Active Record Validations, better explanation of what methods bypass validations<commit_after>h2. Active Record Validations and Callbacks

This guide teaches you how to hook into the lifecycle of your Active Record objects. More precisely, you will learn how to validate the state of your objects before they go into the database as well as how to perform custom operations at certain points in the object lifecycle.

After reading this guide and trying out the presented concepts, we hope that you'll be able to:

* Use the built-in Active Record validation helpers
* Create your own custom validation methods
* Work with the error messages generated by the validation process
* Create callback methods to respond to events in the object lifecycle.
* Create special classes that encapsulate common behavior for your callbacks
* Create Rails Observers

endprologue.

h3. Overview of ActiveRecord Validation

Before you dive into the detail of validations in Rails, you should understand a bit about how validations fit into the big picture. Why should you use validations? When do these validations take place?

h4. Why Use ActiveRecord Validations?

The main reason for validating your objects before they get into the database is to ensure that only valid data is recorded. It's important to be sure that an email address column only contains valid email addresses, or that the customer's name column will never be empty. Constraints like that keep your database organized and helps your application to work properly. 

There are several ways that you could validate the data that goes to the database, including native database constraints, client-side validations, and model-level validations. Each of these has pros and cons:

* Using database constraints and/or stored procedures makes the validation mechanisms database-dependent and may turn your application into a hard to test and maintain beast. However, if your database is used by other applications, it may be a good idea to use some constraints also at the database level. Additionally, database-level validations can safely handle some things (such as uniqueness in heavily-used tables) that are problematic to implement from the application level.
* Implementing validations only at the client side can be difficult in web-based applications. Usually this kind of validation is done using javascript, which may be turned off in the user's browser, leading to invalid data getting inside your database. However, if combined with server side validation, client side validation may be useful, since the user can have a faster feedback from the application when trying to save invalid data.
* Using validation directly in your Active Record classes ensures that only valid data gets recorded, while still keeping the validation code in the right place, avoiding breaking the MVC pattern. Since the validation happens on the server side, the user cannot disable it, so it's also safer. It may be a hard and tedious work to implement some of the logic involved in your models' validations, but fear not: Active Record gives you the ability to easily create validations, providing built-in helpers for common validations while still allowing you to create your own validation methods.

h4. When Does Validation Happen?

There are two kinds of Active Record objects: those that correspond to a row inside your database and those that do not. When you create a fresh object, using the +new+ method, that object does not belong to the database yet. Once you call +save+ upon that object it will be saved into the appropriate database table. Active Record uses the +new_record?+ instance method to determine whether an object is already in the database or not. Consider the following simple Active Record class:

<ruby>
class Person < ActiveRecord::Base
end
</ruby>

We can see how it works by looking at some script/console output:

<shell>
>> p = Person.new(:name => "<NAME>", :birthdate => Date.parse("09/03/1979"))
=> #<Person id: nil, name: "<NAME>", birthdate: "1979-09-03", created_at: nil, updated_at: nil>
>> p.new_record?
=> true
>> p.save
=> true
>> p.new_record?
=> false
</shell>

Creating and saving a new record will send an SQL +INSERT+ operation to the database. Updating an existing record will send an SQL +UPDATE+ operation instead. Validations are run before these commands are sent to the database. If any validations fail, the object will be marked as invalid and Active Record will not trigger the +INSERT+ or +UPDATE+ operation. This helps to avoid storing an object in the database that's invalid. You can choose to have specific validations run when an object is created, saved, or updated.

CAUTION: There are many ways to change the state of an object in the database. Some will trigger validations, and some will not. This means it is possible to save an object in the database that's in an invalid state. Be careful when using Active Record methods that bypass validations.

The following methods trigger validations and generally save the object to the database:

* "create":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002214 (creates an object, but does not save to the database)
* "create!":http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002116
* "save":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002274
* "save!":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002275
* "update":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002215
* "update_attributes":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002281
* "update_attributes!":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002282

The following methods _do not_ trigger validations, but _do_ change the state of the object in the database. They should be used with caution:

* "decrement!":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002286
* "decrement_counter":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002224
* "increment!":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002284
* "increment_counter":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002223
* "toggle":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002287
* "toggle!":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002288
* "update_all":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002218
* "update_attribute":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002280
* "update_counters":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002222

Note that +save+ has the ability to bypass validations. This technique should be used with caution: 

* "save(false)":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002274
{'fraction_non_alphanumeric': 0.05691746543387904, 'fraction_numerical': 0.012045126813130885, 'mean_word_length': 5.0030549898167, 'pattern_counts': {'":': 17, '<': 19, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7059358', 'n_tokens_mistral': 2942, 'n_tokens_neox': 2760, 'n_words': 1614}