Some patterns here for reference:

Value Object

Probably the simplest pattern is Value Object - PORO(plain old ruby object) that provides methods that return values:

class User
  def initialize (full_name:, email:)
    @full_name = full_name
    @email = email
  end

  attr_reader :full_name, :email

  def first_name
    full_name.split(" ").first
  end

  def last_name
    full_name.split(" ").last
  end
end

Service

Service object is responsible for doing only one thing:

class Greeter
  def self.call(name, title)
    "Welcome back #{title}. #{name}!"
  end
end

Of course, in reallity, you will have more complicated logic, but you want to make your service responsible for one thing only (single responsibility rule).

Decorator

Honestly, I am confusing decorators and presenters. I found this explanation and example here:

The decorator pattern is similar to the presenter, but instead of adding additional logic, it alters the original class’s behavior.

We have the Post model that provides a content attribute that contains the post’s content. On the single post page, we would like to render the full content, but on the list, we would like to render just a few words of it:

class PostListDecorator < SimpleDelegator
  def content
    model.content.truncate(50)
  end

  def self.decorate(posts)
    posts.map { |post| new(post) }
  end

  private

  def model
    __getobj__
  end
end

@posts = Post.all
@posts = PostListDecorator.decorate(@posts)

Presenter

This pattern is used when you need to isolate some logic and is usually (not always) used in views.

class UserPresenter
  def initialize(user)
    @user = user
  end

  def role
    if @user.admin?
      'Administrator'
    elsif @user.signed_in
      'User'
    else
      'Guest'
    end
  end
end

Policy Objects

These objects are responsible for permissions, policies etc. Examples of gems will be cancan, pundit

class UserAccoutnPolicy
  def initialize(user, account)
    @user = user
    @account = account
  end

  def access?
    admin? && @account.user == @user
  end

  def close?
    access? && @account.active? && @user.balance.positive?
  end

  private

  def admin?
    @user.role == 'admin'
  end
end

or another example

class BankTransferPolicy
  def self.allowed?(user, recipient, amount)
    user.account_balance >= amount &&
      user.transfers_enabled &&
      user != recipient &&
      amount.positive?
  end
end

Builder

Again, nice example with file parsers from long live ruby

The builder pattern is often also called an adapter. The pattern’s main purpose is to provide a simple way of returning a given class or instance depending on the case. If you are parsing files to get their contents you can create the following builder:

class FileParser
  def self.build(file_path)
    case File.extname(file_path)
      when '.csv' then CsvFileParser.new(file_path)
      when '.xls' then XlsFileParser.new(file_path)
      else
        raise(UnknownFileFormat)
      end
  end
end

class BaseParser
  def initialize(file_path)
    @file_path = file_path
  end
end

class CsvFileParser < BaseParser
  def rows
    # parse rows
  end
end

class XlsFileParser < BaseParser
  def rows
    # parse rows
  end
end

And usage: you can access the rows without worrying about selecting a good class that will be able to parse the given format:

parser = FileParser.build(file_path)
rows = parser.rows

Null object

Nobody likes to deal with nils and having those extra guards and defensive style. If you expect a user in your code, and user is not created (for example guest), rather than check for nil create GuestUser

class GuestUser
  def name
    'Guest'
  end

  def posts
    []
  end
end

Now if you need to perform something with user you don’t need to check for nils and can treat user as it always exists.

user = current_user || GuestUser.new
puts "Welcome #{user.name}"
puts "Number of posts created #{user.posts.size}"

Afterword

Patterns solve problems but when used incorrectly they bring unneeded complexity to your codebase.