Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Validation in model vs migration [duplicate]

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
like image 526
18bytes Avatar asked Oct 29 '12 13:10

18bytes


People also ask

What is difference between model and migration in rails?

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.

What is the purpose of migration in rails?

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.

How rails know which migration is pending?

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.

How do I check my rails migration status?

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.


1 Answers

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)

like image 197
Chris Salzberg Avatar answered Oct 05 '22 10:10

Chris Salzberg