Back to Course

Practice · SOLID · ISP · Card 1

What's the cost of including this big concern everywhere?

A concern that mixes five different capabilities. It got included in every model that needed one of them. What slowly broke?

The code

A "Publishable" concern, included in Post, Comment, Article, and User. Each one needed one or two pieces of it.

module Publishable
  extend ActiveSupport::Concern

  included do
    scope :published, -> { where.not(published_at: nil) }
    scope :draft,     -> { where(published_at: nil) }
    scope :scheduled, -> { where("published_at > ?", Time.current) }
  end

  def publish!;        update!(published_at: Time.current); end
  def unpublish!;      update!(published_at: nil); end
  def reschedule!(at); update!(published_at: at); end
  def published?;      published_at.present? && published_at <= Time.current; end
  def slug;            "#{self.class.name.downcase}-#{id}"; end
end

class Post < ApplicationRecord;    include Publishable; end
class Comment < ApplicationRecord; include Publishable; end
class Article < ApplicationRecord; include Publishable; end
class User < ApplicationRecord;    include Publishable; end

The question

Comments don't get scheduled. Users don't have slugs. What's the actual cost of including this big concern in every model that needed just a piece of it?

Take a moment. The interface-segregation principle says: don't make clients depend on methods they don't use. What goes wrong here over time?