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
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
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
So what is
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