Maintenance: Added methods to get list of tagged objects or references to them in backend code.

This commit is contained in:
Mantas Masalskis 2021-08-16 07:57:44 +02:00 committed by Martin Gruner
parent cb5a9dfb14
commit 28829c334b
4 changed files with 135 additions and 0 deletions

View file

@ -77,4 +77,45 @@ destroy all tags of an object
true
end
class_methods do
=begin
Lists references to objects of this type with certain tag.
Returns array containing object IDs.
@param [String] tag name
@example
Model.tag_references('Tag') # [1, 4, ...]
@return [Array<Integer>]
=end
def tag_references(tag)
Tag
.tag_references(tag: tag, object: name)
.map { |elem| elem[1] }
end
=begin
Lists objects of this type with certain tag
@param [String] tag name
@example
Model.tag_objects('tag')
@return [ActiveRecord::Relation]
=end
def tag_objects(tag)
where id: tag_references(tag)
end
end
end

View file

@ -152,4 +152,37 @@ returns
.order(:id)
.pluck('tag_items.name')
end
=begin
Lists references to objects with certain tag. Optionally filter by type.
Returns array containing object class name and ID.
@param tag [String] tag to lookup
@param object [String] optional name of the class to search in
@example
references = Tag.tag_references(
tag: 'Tag',
object: 'Ticket'
)
references # [['Ticket', 1], ['Ticket', 4], ...]
@return [Array<Array<String, Integer>>]
=end
def self.tag_references(tag:, object: nil)
tag_item = Tag::Item.find_by name: tag
return [] if tag_item.nil?
output = Tag.where(tag_item: tag_item).joins(:tag_object)
output = output.where(tag_objects: { name: object }) if object.present?
output.pluck(:'tag_objects.name', :o_id)
end
end

View file

@ -65,4 +65,37 @@ RSpec.shared_examples 'HasTags' do
subject.tag_list
end
end
shared_context 'with subject and another object being tagged', current_user_id: 1 do
before do
subject.tag_add(tag)
Tag.tag_add(object: 'AnotherObject', o_id: 123, item: tag)
end
let(:tag) { 'tag_name' }
end
describe '.tag_references' do
include_context 'with subject and another object being tagged' do
it 'returns reference to subject' do
expect(described_class.tag_references(tag)).to match_array [subject.id]
end
it 'does not return reference to subject when called with other tag' do
expect(described_class.tag_references('other')).to be_blank
end
end
end
describe '.tag_objects' do
include_context 'with subject and another object being tagged' do
it 'returns subject' do
expect(described_class.tag_objects(tag)).to match_array [subject]
end
it 'does not return subject when called with other tag' do
expect(described_class.tag_objects('other')).to be_blank
end
end
end
end

View file

@ -156,4 +156,32 @@ RSpec.describe Tag, type: :model do
end
end
end
describe '.tag_references' do
context 'with objects with a tag', current_user_id: 1 do
before do
[object_1, object_2].each do |elem|
described_class.tag_add object: elem.class.name, o_id: elem.id, item: tag
end
end
let(:object_1) { create(:ticket) }
let(:object_2) { create(:knowledge_base_answer) }
let(:tag) { 'foo' }
it 'returns references' do
expect(described_class.tag_references(tag: tag)).to match_array [
[object_1.class.name, object_1.id],
[object_2.class.name, object_2.id]
]
end
it 'returns references for the given object type' do
expect(described_class.tag_references(tag: tag, object: 'Ticket')).to match_array [
[object_1.class.name, object_1.id]
]
end
end
end
end