rails-pattern_matching

This gem provides the pattern matching interface for ActiveModel::AttributeMethods, ActiveRecord::Base, and ActiveRecord::Relation.

That means it allows you to write code using the pattern matching against your Rails models like the following example:

# app/models/post.rb
class Post < ApplicationRecord
  has_many :comments
end

# app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :post
end

# app/helpers/posts_helper.rb
module PostsHelper
  def comment_header_for(post)
    case post
    # Here we're matching against an attribute on the post that is an
    # association. It will go through the association and then match against the
    # records in the relation.
    in { comments: [] }
      "No comments yet"
    # Here we're searching for a comment that has the same user_id as the post.
    # We can do this with the "find" pattern. This syntax is all baked into
    # Ruby, so we don't have to do anything other than define the requisite
    # deconstruct methods that are used by the pattern matching.
    in { comments: [*, { user_id: ^(post.user_id ) }, *] }
      "Host replied"
    # Here we're extracting the first comment out of the comments association.
    in { comments: [comment] }
      "One comment"
    # Here we provide a default in case none of the above match. Since we have
    # already matched against an empty array of comments and a single element
    # array, we know that there are at least two comments. We can get the length
    # of the comments association by capturing the comments association in the
    # pattern itself and then using it.
    in { comments: }
      "#{comments.length} comments"
    end
  end
end

Installation

Add this line to your application's Gemfile:

gem "rails-pattern_matching"

And then execute:

$ bundle

Or install it yourself as:

$ gem install rails-pattern_matching

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/kddnewton/rails-pattern_matching.

License

The gem is available as open source under the terms of the MIT License.