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
in { comments: [] }
# 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.
"No comments yet"
in { user_id:, comments: [*, { user_id: ^user_id }, *] }
# 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.
"Host replied"
in { comments: [{ user: { name: } }] }
# Here we're extracting the first comment out of the comments association
# and using its associated user's name in the header.
"One comment from #{name}"
in { comments: }
# 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.
"#{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.