Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What type of language construct is Rails' "validates"?

I'm just starting to grok Ruby. My background is in .NET and PHP. In Rails, and I'm sure in other frameworks as well, I see stuff like this on classes:

class Person < ActiveRecord::Base
    validates :terms_of_service, :acceptance => true
end

What exactly is "validates"? Is it a function? If it's a function, how does the validation actually work since you don't tell the validates function which model you are validating?

Where can I read more about how this actually works behind the scenes?

like image 424
TaylorOtwell Avatar asked Dec 22 '22 05:12

TaylorOtwell


2 Answers

It's... a little complicated - but the short answer is that validates is a class method of Person, inherited from ActiveRecord::Base. That line could equally have been written validates(:terms_of_service, :acceptance => true).

Ruby, like a lot of interpreted languages, effectively "executes" class definitions, so when it encounters the validates line, it sees it as a method call where the current self object is the instance of the Class class representing the class Person, inheriting from ActiveRecord::Base. It calls the method, which has the effect of hooking a validator into the Person class.

You can read about the method here - but do note that that adds more confusion, since it lists the method as an instance method of ActiveModel::Validations::ClassMethods. Huh? Well, Ruby has two ways of taking functionality from another Module and putting it into your class - you can either include the module (in which case its instance methods become instance methods of your class), or extend the module (in which case its instance methods become class methods of your class).

So, to summarise: validates is declared as an instance method of ActiveModel::Validations::ClassMethods, which is extended into ActiveRecord::Base. Therefore, validates is a class method of ActiveRecord::Base and, by inheritance, Person. The line in your code snippet is just a method call.

However, having said all that, most Rubyists and Railsists will largely ignore those facts; validates is what's called a "decorator", and most people will simply read it as a statement about Person.

like image 81
Chowlett Avatar answered Jan 03 '23 01:01

Chowlett


It's a special callback method that gets called to validate data before it's saved to the database.

A callback, more generally, is a method that "hooks into" an object or code module/library in such a way that the method gets called automatically when certain events occur. In this case, the event that calls the set of validation methods is the act of trying to save something to the database. This is useful because, before you write new or updated information to your database, you want to make sure it's valid, in order to prevent bad data from leaking into your application.

The following methods trigger validations, and will save the object to the database only if all validations pass (in the literal sense, this means all the validation methods must return a value that is not false, or nil, etc., otherwise validation is considered to have failed):

  • create
  • create!
  • save
  • save!
  • update
  • update_attributes
  • update_attributes!

"Methods" in Ruby are very similar to the concept of functions in other languages. In many cases you can think of them interchangeably - they declare some functionality, they take parameters as input, and they return a result as output.

More detail on validations: http://guides.rubyonrails.org/active_record_validations_callbacks.html

Ruby (and Rails) use "callbacks" in many different situations - pretty much anytime you want some method to be called as a result of some event occuring.

More reading on callbacks: http://www.khelll.com/blog/ruby/ruby-callbacks/

like image 22
jefflunt Avatar answered Jan 03 '23 02:01

jefflunt