Skip to content

Commit

Permalink
Allow prefix and suffix wildcard tag search (#1082)
Browse files Browse the repository at this point in the history
  • Loading branch information
glampr committed Apr 26, 2022
1 parent bc55548 commit 2014fcc
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 4 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ Each change should fall into categories that would affect whether the release is

As such, _Breaking Changes_ are major. _Features_ would map to either major or minor. _Fixes_, _Performance_, and _Misc_ are either minor or patch, the difference being kind of fuzzy for the purposes of history. Adding _Documentation_ (including tests) would be patch level.

### [v9.0.1) / 2022-01-07](https://github.com/mbleigh/acts-as-taggable-on/compare/v8.1.0...v9.0.0)
### [v9.0.2) / unreleased](https://github.com/mbleigh/acts-as-taggable-on/compare/v9.0.1...master)
* Features
* [@glampr Add support for prefix and suffix searches alongside previously supported containment (wildcard) searches](https://github.com/mbleigh/acts-as-taggable-on/pull/1082)

### [v9.0.1) / 2022-01-07](https://github.com/mbleigh/acts-as-taggable-on/compare/v9.0.0..v9.0.1)
* Fixes
* Fix migration that generate default index

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,11 @@ User.tagged_with(["awesome", "cool"], :exclude => true)
User.tagged_with(['awesome', 'cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
```

You can also use `:wild => true` option along with `:any` or `:exclude` option. It will be looking for `%awesome%` and `%cool%` in SQL.
#### Wildcard tag search
You now have the following options for prefix, suffix and containment search, along with `:any` or `:exclude` option.
Use `wild: :suffix` to place a wildcard at the end of the tag. It will be looking for `awesome%` and `cool%` in SQL.
Use `wild: :prefix` to place a wildcard at the beginning of the tag. It will be looking for `%awesome` and `%cool` in SQL.
Use `wild: true` to place a wildcard both at the beginning and the end of the tag. It will be looking for `%awesome%` and `%cool%` in SQL.

__Tip:__ `User.tagged_with([])` or `User.tagged_with('')` will return `[]`, an empty set of records.

Expand Down
13 changes: 11 additions & 2 deletions lib/acts_as_taggable_on/taggable/tagged_with_query/query_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def tag_match_type(tag)
matches_attribute = matches_attribute.lower unless ActsAsTaggableOn.strict_case_match

if options[:wild].present?
matches_attribute.matches("%#{escaped_tag(tag)}%", '!', ActsAsTaggableOn.strict_case_match)
matches_attribute.matches(wildcard_escaped_tag(tag), '!', ActsAsTaggableOn.strict_case_match)
else
matches_attribute.matches(escaped_tag(tag), '!', ActsAsTaggableOn.strict_case_match)
end
Expand All @@ -45,7 +45,7 @@ def tags_match_type

if options[:wild].present?
matches_attribute.matches_any(tag_list.map do |tag|
"%#{escaped_tag(tag)}%"
wildcard_escaped_tag(tag)
end, '!', ActsAsTaggableOn.strict_case_match)
else
matches_attribute.matches_any(tag_list.map do |tag|
Expand All @@ -59,6 +59,15 @@ def escaped_tag(tag)
ActsAsTaggableOn::Utils.escape_like(tag)
end

def wildcard_escaped_tag(tag)
case options[:wild]
when :suffix then "#{escaped_tag(tag)}%"
when :prefix then "%#{escaped_tag(tag)}"
when true then "%#{escaped_tag(tag)}%"
else escaped_tag(tag)
end
end

def adjust_taggings_alias(taggings_alias)
taggings_alias = "taggings_alias_#{Digest::SHA1.hexdigest(taggings_alias)}" if taggings_alias.size > 75
taggings_alias
Expand Down
4 changes: 4 additions & 0 deletions spec/acts_as_taggable_on/taggable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,10 @@
jim = TaggableModel.create(name: 'Jim', tag_list: 'jim, steve')

expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, any: true).to_a.sort_by { |o| o.id }).to eq([bob, frank, steve])
expect(TaggableModel.tagged_with(%w(bob tricia), wild: :prefix, any: true).to_a.sort_by { |o| o.id }).to eq([bob, steve])
expect(TaggableModel.tagged_with(%w(bob tricia), wild: :suffix, any: true).to_a.sort_by { |o| o.id }).to eq([bob, frank])
expect(TaggableModel.tagged_with(%w(cia), wild: :prefix, any: true).to_a.sort_by { |o| o.id }).to eq([bob, steve])
expect(TaggableModel.tagged_with(%w(j), wild: :suffix, any: true).to_a.sort_by { |o| o.id }).to eq([frank, steve, jim])
expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, exclude: true).to_a).to eq([jim])
expect(TaggableModel.tagged_with('ji', wild: true, any: true).to_a).to match_array([frank, jim])
end
Expand Down

0 comments on commit 2014fcc

Please sign in to comment.