From 6b6586f5d099a9089c8bf9dc7d7406a86c0a48eb Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 25 Jan 2024 08:00:34 -0500 Subject: [PATCH] Add `CustomFilterKeyword#to_regex` method (#28893) --- app/models/custom_filter.rb | 11 +------ app/models/custom_filter_keyword.rb | 16 +++++++++++ spec/models/custom_filter_keyword_spec.rb | 35 +++++++++++++++++++++++ 3 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 spec/models/custom_filter_keyword_spec.rb diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index 371267fc28..c8120c2395 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -68,16 +68,7 @@ class CustomFilter < ApplicationRecord scope = CustomFilterKeyword.includes(:custom_filter).where(custom_filter: { account_id: account_id }).where(Arel.sql('expires_at IS NULL OR expires_at > NOW()')) scope.to_a.group_by(&:custom_filter).each do |filter, keywords| - keywords.map! do |keyword| - if keyword.whole_word - sb = /\A[[:word:]]/.match?(keyword.keyword) ? '\b' : '' - eb = /[[:word:]]\z/.match?(keyword.keyword) ? '\b' : '' - - /(?mix:#{sb}#{Regexp.escape(keyword.keyword)}#{eb})/ - else - /#{Regexp.escape(keyword.keyword)}/i - end - end + keywords.map!(&:to_regex) filters_hash[filter.id] = { keywords: Regexp.union(keywords), filter: filter } end.to_h diff --git a/app/models/custom_filter_keyword.rb b/app/models/custom_filter_keyword.rb index 3158b3b79a..979d0b822e 100644 --- a/app/models/custom_filter_keyword.rb +++ b/app/models/custom_filter_keyword.rb @@ -23,8 +23,24 @@ class CustomFilterKeyword < ApplicationRecord before_destroy :prepare_cache_invalidation! after_commit :invalidate_cache! + def to_regex + if whole_word? + /(?mix:#{to_regex_sb}#{Regexp.escape(keyword)}#{to_regex_eb})/ + else + /#{Regexp.escape(keyword)}/i + end + end + private + def to_regex_sb + /\A[[:word:]]/.match?(keyword) ? '\b' : '' + end + + def to_regex_eb + /[[:word:]]\z/.match?(keyword) ? '\b' : '' + end + def prepare_cache_invalidation! custom_filter.prepare_cache_invalidation! end diff --git a/spec/models/custom_filter_keyword_spec.rb b/spec/models/custom_filter_keyword_spec.rb new file mode 100644 index 0000000000..4e3ab060a0 --- /dev/null +++ b/spec/models/custom_filter_keyword_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe CustomFilterKeyword do + describe '#to_regex' do + context 'when whole_word is true' do + it 'builds a regex with boundaries and the keyword' do + keyword = described_class.new(whole_word: true, keyword: 'test') + + expect(keyword.to_regex).to eq(/(?mix:\b#{Regexp.escape(keyword.keyword)}\b)/) + end + + it 'builds a regex with starting boundary and the keyword when end with non-word' do + keyword = described_class.new(whole_word: true, keyword: 'test#') + + expect(keyword.to_regex).to eq(/(?mix:\btest\#)/) + end + + it 'builds a regex with end boundary and the keyword when start with non-word' do + keyword = described_class.new(whole_word: true, keyword: '#test') + + expect(keyword.to_regex).to eq(/(?mix:\#test\b)/) + end + end + + context 'when whole_word is false' do + it 'builds a regex with the keyword' do + keyword = described_class.new(whole_word: false, keyword: 'test') + + expect(keyword.to_regex).to eq(/test/i) + end + end + end +end