Last active
July 7, 2022 23:33
-
-
Save harssh-sparkway/8707634 to your computer and use it in GitHub Desktop.
Don’t Repeat Yourself (DRY) in Ruby on Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Don’t Repeat Yourself (DRY) in Ruby on Rails | |
#DRY (Don’t Repeat Yourself) is a principle of Software Development to reducing repetition of information or codes. We can #apply DRY quite broadly to database schema, test plan, system, even documentation. And in this post, we will take example of DRY #in Ruby on Rails development. | |
#In particular case, 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 | |
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 | |
#When the DRY principle is applied successfully, a modification of any single element of a system does not require a change in #other logically unrelated elements. Additionally, elements that are logically related all change predictably and uniformly, and #are thus kept in sync. This makes your code more DRY and more clean. And adding more states makes it more easy to modify. |
More DRYing by using enums
class Article < ActiveRecord::Base enum state: [:draft, :published, :spam] end
More info about enums ActiveRecord::Enum
Nice
I googled "Dry in rails" and came across this gist. Congratulations. It's ranking quite highly!
But I was googling that because there was a hackernews discussion today about people over-using the DRY principle, and some folks saying that Rails developers are the worst at this.
I do wonder if this gist is a case in point. Surely the "before" code is actually more readable than loops doing calls to define_method
. Aren't we eliminating repetition at the cost of code clarity here?
The by_state(state)
suggestion by @hiro-riveros is a lot cleaner, although that assumes we can change all the calling code.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
or maybe by state?