Skip to content

Commit

Permalink
Add :tenant option to :tagged_with
Browse files Browse the repository at this point in the history
  • Loading branch information
sigra committed Dec 6, 2023
1 parent 46c4e2d commit e71101e
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Changes are below categorized as follows:
- Breaking Changes
- Features
* [@flickgradley Add tenant: option to tagged_with](https://github.com/mbleigh/acts-as-taggable-on/pull/1102)
- Fixes
- Performance
- Misc
Expand Down
4 changes: 4 additions & 0 deletions lib/acts_as_taggable_on/taggable/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def grouped_column_names_for(object)
# * <tt>:owned_by</tt> - return objects that are *ONLY* owned by the owner
# * <tt>:start_at</tt> - Restrict the tags to those created after a certain time
# * <tt>:end_at</tt> - Restrict the tags to those created before a certain time
# * <tt>:tenant</tt> - *ONLY* consider tags with a given tenant
#
# Example:
# User.tagged_with(["awesome", "cool"]) # Users that are tagged with awesome and cool
Expand All @@ -106,6 +107,9 @@ def grouped_column_names_for(object)
# User.tagged_with(["awesome", "cool"], :match_all => true) # Users that are tagged with just awesome and cool
# User.tagged_with(["awesome", "cool"], :owned_by => foo ) # Users that are tagged with just awesome and cool by 'foo'
# User.tagged_with(["awesome", "cool"], :owned_by => foo, :start_at => Date.today ) # Users that are tagged with just awesome, cool by 'foo' and starting today
# User.tagged_with(["awesome", "cool"], :tenant => "account_15") # Users that are tagged with awesome and cool within the "account_15" tenant
# User.tagged_with(["awesome", "cool"], :tenant => "account_15", :any => true ) # Users that are tagged with awesome or cool within the "account_15" tenant
# User.tagged_with(["awesome", "cool"], :tenant => "account_15", :exclude => true ) # Users that are not tagged with awesome or cool within the "account_15" tenant
def tagged_with(tags, options = {})
tag_list = ActsAsTaggableOn.default_parser.new(tags).parse
options = options.dup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def on_conditions(tag, tagging_alias)
.and(tagging_alias[:tagger_type].eq(owner.class.base_class.to_s))
end

if options[:tenant].present?
on_condition = on_condition.and(tagging_alias[:tenant].eq(options[:tenant]))
end

on_condition
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def at_least_one_tag
.and(tagging_arel_table[:tagger_type].eq(owner.class.base_class.to_s))
end

if options[:tenant].present?
exists_contition = exists_contition.and(tagging_arel_table[:tenant].eq(options[:tenant]))
end

exists_contition
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@ def build
private

def tags_not_in_list
arel_join_on = tagging_arel_table[:tag_id].eq(tag_arel_table[:id])
.and(tagging_arel_table[:taggable_type].eq(taggable_model.base_class.name))
.and(tags_match_type)

if options[:tenant]
arel_join_on = arel_join_on.and(tagging_arel_table[:tenant].eq(options[:tenant]))
end

taggable_arel_table[:id].not_in(
tagging_arel_table
.project(tagging_arel_table[:taggable_id])
.join(tag_arel_table)
.on(
tagging_arel_table[:tag_id].eq(tag_arel_table[:id])
.and(tagging_arel_table[:taggable_type].eq(taggable_model.base_class.name))
.and(tags_match_type)
)
.on(arel_join_on)
)

# FIXME: missing time scope, this is also missing in the original implementation
Expand Down Expand Up @@ -67,6 +71,10 @@ def match_all_on_conditions

on_condition = on_condition.and(tagging_arel_table[:context].eq(options[:on])) if options[:on].present?

if options[:tenant].present?
on_condition = on_condition.and(tagging_arel_table[:tenant].eq(options[:tenant]))
end

on_condition
end

Expand Down
37 changes: 37 additions & 0 deletions spec/acts_as_taggable_on/taggable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,43 @@
expect(TaggableModel.tagged_with('lazy', exclude: true).size).to eq(2)
end

it 'should be able to find tagged with any tag belonging to a tenant' do
bob = TaggableModel.create(name: 'Bob', tag_list: 'fitter, happier, more productive', skill_list: 'ruby, rails, css', tenant_id: 1)
frank = TaggableModel.create(name: 'Frank', tag_list: 'weaker, depressed, inefficient', skill_list: 'ruby, rails, css', tenant_id: 1)
steve = TaggableModel.create(name: 'Steve', tag_list: 'fitter, happier, more productive', skill_list: 'c++, java, ruby', tenant_id: 2)

expect(TaggableModel.tagged_with(%w(ruby java), tenant: 1, order: 'taggable_models.name', any: true).to_a).to eq([bob, frank])
expect(TaggableModel.tagged_with(%w(ruby java), tenant: 2, order: 'taggable_models.name', any: true).to_a).to eq([steve])
expect(TaggableModel.tagged_with(%w(c++ fitter), tenant: 1, order: 'taggable_models.name', any: true).to_a).to eq([bob])
expect(TaggableModel.tagged_with(%w(c++ fitter), tenant: 2, order: 'taggable_models.name', any: true).to_a).to eq([steve])
expect(TaggableModel.tagged_with(%w(depressed css), tenant: 1, order: 'taggable_models.name', any: true).to_a).to eq([bob, frank])
expect(TaggableModel.tagged_with(%w(depressed css), tenant: 2, order: 'taggable_models.name', any: true).to_a).to eq([])
end

it 'should be able to find tagged belonging to a tenant' do
bob = TaggableModel.create(name: 'Bob', tag_list: 'fitter, happier, more productive', skill_list: 'ruby, rails, css', tenant_id: 1)
frank = TaggableModel.create(name: 'Frank', tag_list: 'weaker, depressed, inefficient', skill_list: 'ruby, rails, css', tenant_id: 2)
steve = TaggableModel.create(name: 'Steve', tag_list: 'fitter, happier, more productive', skill_list: 'c++, java, ruby', tenant_id: 2)

expect(TaggableModel.tagged_with('ruby', tenant: 1, order: 'taggable_models.name').to_a).to eq([bob])
expect(TaggableModel.tagged_with('ruby', tenant: 2, order: 'taggable_models.name').to_a).to eq([frank, steve])
expect(TaggableModel.tagged_with('ruby, rails', tenant: 1, order: 'taggable_models.name').to_a).to eq([bob])
expect(TaggableModel.tagged_with('ruby, rails', tenant: 2, order: 'taggable_models.name').to_a).to eq([frank])
expect(TaggableModel.tagged_with(%w(ruby rails), tenant: 1, order: 'taggable_models.name').to_a).to eq([bob])
expect(TaggableModel.tagged_with(%w(ruby rails), tenant: 2, order: 'taggable_models.name').to_a).to eq([frank])
end

it 'should be able to find tagged with some excluded tags' do
bob = TaggableModel.create(name: 'Bob', tag_list: 'happier, lazy', tenant_id: 1)
frank = TaggableModel.create(name: 'Frank', tag_list: 'happier, lazy', tenant_id: 2)
steve = TaggableModel.create(name: 'Steve', tag_list: 'happier', tenant_id: 2)

expect(TaggableModel.tagged_with('lazy', tenant: 1, exclude: true)).to eq([frank, steve])
expect(TaggableModel.tagged_with('lazy', tenant: 2, exclude: true)).to eq([bob, steve])
expect(TaggableModel.tagged_with('happier', tenant: 1, exclude: true)).to eq([frank, steve])
expect(TaggableModel.tagged_with('happier', tenant: 2, exclude: true)).to eq([bob])
end

it 'should return an empty scope for empty tags' do
['', ' ', nil, []].each do |tag|
expect(TaggableModel.tagged_with(tag)).to be_empty
Expand Down

0 comments on commit e71101e

Please sign in to comment.