Keeping ruby on rails model DRY - MetaProgramming
If you find some methods whose definitions are more or less similar, only different by the method name, it may use meta programming to simplify the things to make your model more clean and DRY.
Consider this simple example where we have an article with three states.
Before
class Article < ActiveRecord::Base
def self.all_published
where("state = ?", "published")
end
def self.all_draft
where("state = ?", "draft")
end
def self.all_spam
where("state = ?", "spam")
end
def published?
self.state == 'published'
end
def draft?
self.state == 'draft'
end
def spam?
self.state == 'spam'
end
end
Now this code can be written as:
After
class Article < ActiveRecord::Base
STATES = ['draft', 'published', 'spam']
class <<self
STATES.each do |state_name|
define_method "all_#{state_name}" do
where("state = ?", state_name)
end
end
end
STATES.each do |state_name|
define_method "#{state_name}?" do
self.state == state_name
end
end
end
This makes your code drier and cleaner. And adding more states makes it easier to modify.