Possible Duplicate:
Ruby on Rails: Is it better to validate in the model or the database?
I see that it's possible to add same constraint/validation in both Rails model and migration. But which one is the best approach? Is it a good practice to validate both at model and database level (and why)? or they same in rails?
For e.g. We can do same validation for name in both model and migration
class User < ActiveRecord::Base
validates :name, :uniqueness => true, :presence => true
end
class CreateUser < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name, :unique => true, :null => false
end
end
end
Rails Model (Active Record) works with SQL, and Rails Migration works with DDL. Rails Model supports ways to interact to with the database, while Rails Migration changes the database structure. A migration can change the name of a column in books table.
The main purpose of Rails' migration feature is to issue commands that modify the schema using a consistent process. Migrations can also be used to add or modify data. This is useful in an existing database that can't be destroyed and recreated, such as a production database.
Rails provides a configuration option to indicate if we want to be alerted if any migration is pending. This will raise an error of the pending migrations and notify the user as shown in the image below. This can be disabled with the false value for the option as shown below.
To check for status, run rails db:migrate:status . Then you'll have a good view of the migrations you want to remove. Then, run rails db:rollback to revert the changes one by one.
Wherever possible, validate at the database level as well as at the model level.
Why? For starters, active record does not enforce validation in all contexts. The following methods skip validations, and will save the object to the database regardless of its validity:
decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_counters
If you pass :validate => false
to save
, it will also skip validation. See the Active Record Validations and Callbacks Guide section on Skipping Validations for details. (If this worries you, there is even a gem for disabling these methods.)
So reason #1 is that Rails validations are not full-proof by any means: relying on them exclusively is risky, particularly for mission-critical validations such as uniqueness.
Speaking of which, reason #2 (off the top of my head): activerecord validations are prone to race conditions, and Rails' uniqueness validator in particular cannot guarantee uniqueness. Here's one article among many that documents why this is so.
Although they may be a rare occurrence, violations of uniqueness constraints can corrupt an entire data set. In the rare case that Rails is about to do this, you want at all costs to stop it, which is where the DB uniqueness constraint comes in: databases are built to handle this situation and will enforce uniqueness consistently, even when Rails does not.
And reason #3: why not validate both in the model and in the DB? Sure, you duplicate a bit, but that's generally a pretty minor concern compared with the payoff if Rails misses something like a uniqueness validation check. This is really not an either/or proposition: it's always better to duplicate validation in the DB wherever you can, particularly for mission-critical constraints such as uniqueness.
Anyway, those are my thoughts, hope that helps.
Ref: Where Correctness Is Enforced (screencast by Gary Bernhardt, need subscription to view)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With