In ruby, you often execute methods like has_many
or validates
when you instanciate a class. Is there a name to designate this kind of method specifically created to be called at class instanciation ?
CodePudding user response:
Building on Stefan's excellent comment...
They are inherited class methods forming a domain specific language used to make declarations about the class.
Those are all class methods, so called because you call then directly on the class. self
will be the class. As opposed to instance methods which are called on the instance of the class, the object.
They are also inherited methods from ActiveRecord
, they are
not defined within your class but in an ancestor class or module.
More specifically, they form a domain specific language; a DSL. These are method calls written in a specific way to seem like a new language. For example,
class Player < ApplicationRecord
validates :terms_of_service, presence: true, acceptance: { message: 'must be abided' }
end
Is really...
Player.validates(
:terms_of_service,
presence: true,
acceptance: { message: 'must be abided' }
)
Which is a wrapper around...
Player.validates_presence_of(:terms_of_service)
Player.validates_acceptance_of(:terms_of_service, message: 'must be abided')
Which is a wrapper around...
Player.validates_with(PresenceValidator, :terms_of_service)
Player.validates_with(AcceptanceValidator, :terms_of_service, message: 'must be abided')
Which is a wrapper around pushing validation objects onto a Hash of validations for this class.
# Roughly...
Player._validators[:terms_of_service] <<
PresenceValidator.new(
attributes: [:terms_of_service]
)
Player._validators[:terms_of_service] <<
AcceptanceValidator.new(
attributes: [:terms_of_service],
message: 'must be abided'
)
Finally, Domain Specific Languages are form of declarative programming.
In other types of programming you tell the program how to do it. For example, let's say you wanted to make sure an attribute is a positive integer greater than zero. You can do it procedurally...
object.number.match?(/^\d $/) && object.number > 0
Or you ask a specific method to do it...
NumericalityValidator.new(
attribute: [:number],
only_integer: true, greater_than: 0
).validate(object)
But in declarative programming you declare how it's going to be and the language figures out how to make it happen.
class Player < ApplicationRecord
validates :number, numericality: { only_integer: true, greater_than: 0 }
end
You probably already know two declarative languages: SQL and Regular Expressions.