Rails concern
This is part of the code in Launch School 301 course. And in the code below, it shows how to extract the duplicate code in different module to ActiveSupport::Concern
. But there are more than one way to refactor the code. DHH in the signal v. Noise wrote an article to introduce the concerns
:
Different models in your Rails application will often share a set of cross-cutting concerns. In Basecamp, we have almost forty such concerns with names like Trashable, Searchable, Visible, Movable, Taggable.
Ryan Bates of Railscasts wrote an article to talk to people not to use concern. He encourage people to use Service Object
.
module Sluggable
extend ActiveSupport::Concern
included do
before_save :generate_slug!
class_attribute :slug_column
end
def to_param
self.slug
end
def generate_slug!
the_slug = to_slug(self.send(self.class.slug_column.to_sym))
obj = self.class.find_by slug: the_slug
count = 2
while obj && obj != self
the_slug = append_suffix(the_slug, count)
obj = self.class.find_by slug: the_slug
count += 1
end
self.slug = the_slug.downcase
end
def append_suffix(str, count)
if str.split('_').last.to_i != 0
return str.split('_').slice(0...-1).join('_') + '_' + count.to_s
else
return str + '_' + count.to_s
end
end
def to_slug(name)
str = name.strip
str.gsub!(/\s*[^A-Za-z0-9]\s*/, '_')
str.gsub!( /_+/, "_")
str.downcase
end
module ClassMethods
def sluggable_column(col_name)
self.slug_column = col_name
end
end
end
Is there more than one way to solve this problem?
Of course! The ActiveSupport::Concern
was introduced in rails 4. After that, there are plenty ways to extract the duplicate code. One is also popular is use Service Object
So what is service object
?
A service object (aka method object) performs one action. It holds the business logic to perform that action
It can not only refactor model but also controller! Besides, you can understand what each service object do(it is a class) better than in concern. And it can write a test to test the service object.
Read more on this article
Resources:
- You can see the compare of the
concern
way, comparing withservice object
way to refactor the code in the Railscasts #398 Service Objects - There are an article: 7 patterns to refactor models. It is worth reading it.