Add helper method to intelligently create new rules (avoiding duplicates)
This commit is contained in:
parent
fd333d59b7
commit
aa6430e23e
|
@ -1,6 +1,7 @@
|
||||||
module DiscourseChat
|
module DiscourseChat
|
||||||
module Helper
|
module Helper
|
||||||
|
|
||||||
|
# Produce a string with a list of all rules associated with a channel
|
||||||
def self.status_for_channel(provider, channel)
|
def self.status_for_channel(provider, channel)
|
||||||
rules = DiscourseChat::Rule.all_for_channel(provider, channel)
|
rules = DiscourseChat::Rule.all_for_channel(provider, channel)
|
||||||
|
|
||||||
|
@ -40,6 +41,61 @@ module DiscourseChat
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create a rule for a specific channel
|
||||||
|
# Designed to be used by provider's "Slash commands"
|
||||||
|
# Will intelligently adjust existing rules to avoid duplicates
|
||||||
|
# Returns
|
||||||
|
# :updated if an existing rule has been updated
|
||||||
|
# :created if a new rule has been created
|
||||||
|
# false if there was an error
|
||||||
|
def self.smart_create_rule(provider:, channel:, filter:, category_id:, tags:)
|
||||||
|
existing_rules = DiscourseChat::Rule.all_for_channel(provider, channel)
|
||||||
|
|
||||||
|
# Select the ones that have the same category
|
||||||
|
same_category = existing_rules.select { |rule| rule.category_id == category_id }
|
||||||
|
|
||||||
|
same_category_and_tags = same_category.select{ |rule| (rule.tags.nil? ? [] : rule.tags.sort) == (tags.nil? ? [] : tags.sort) }
|
||||||
|
|
||||||
|
if same_category_and_tags.size > 0
|
||||||
|
# These rules have exactly the same criteria as what we're trying to create
|
||||||
|
the_rule = same_category_and_tags.shift # Take out the first one
|
||||||
|
|
||||||
|
same_category_and_tags.each do |rule| # Destroy all the others - they're duplicates
|
||||||
|
rule.destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
return :updated if the_rule.update(filter:filter) # Update the filter
|
||||||
|
return false # Error, probably validation
|
||||||
|
end
|
||||||
|
|
||||||
|
same_category_and_filters = same_category.select { |rule| rule.filter == filter }
|
||||||
|
|
||||||
|
if same_category_and_filters.size > 0
|
||||||
|
# These rules are exactly the same, except for tags. Let's combine the tags together
|
||||||
|
tags = [] if tags.nil?
|
||||||
|
same_category_and_filters.each do |rule|
|
||||||
|
tags = tags | rule.tags unless rule.tags.nil? # Append the tags together, avoiding duplicates by magic
|
||||||
|
end
|
||||||
|
|
||||||
|
the_rule = same_category_and_filters.shift # Take out the first one
|
||||||
|
|
||||||
|
if the_rule.update(tags: tags) # Update the tags
|
||||||
|
same_category_and_filters.each do |rule| # Destroy all the others - they're duplicates
|
||||||
|
rule.destroy
|
||||||
|
end
|
||||||
|
return :updated
|
||||||
|
end
|
||||||
|
|
||||||
|
return false # Error
|
||||||
|
end
|
||||||
|
|
||||||
|
# This rule is unique! Create a new one:
|
||||||
|
return :created if Rule.new({provider: provider, channel: channel, filter: filter, category_id: category_id, tags: tags}).save
|
||||||
|
|
||||||
|
return false # Error
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ RSpec.describe DiscourseChat::Manager do
|
||||||
|
|
||||||
let(:category) {Fabricate(:category)}
|
let(:category) {Fabricate(:category)}
|
||||||
let(:tag1){Fabricate(:tag)}
|
let(:tag1){Fabricate(:tag)}
|
||||||
|
let(:tag2){Fabricate(:tag)}
|
||||||
|
let(:tag3){Fabricate(:tag)}
|
||||||
|
|
||||||
describe '.status_for_channel' do
|
describe '.status_for_channel' do
|
||||||
|
|
||||||
|
@ -54,4 +56,93 @@ RSpec.describe DiscourseChat::Manager do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.smart_create_rule' do
|
||||||
|
|
||||||
|
it 'creates a rule when there are none' do
|
||||||
|
val = DiscourseChat::Helper.smart_create_rule(provider: 'slack',
|
||||||
|
channel: '#general',
|
||||||
|
filter: 'watch',
|
||||||
|
category_id: category.id,
|
||||||
|
tags: [tag1.name]
|
||||||
|
)
|
||||||
|
expect(val).to eq(:created)
|
||||||
|
|
||||||
|
record = DiscourseChat::Rule.all.first
|
||||||
|
expect(record.provider).to eq('slack')
|
||||||
|
expect(record.channel).to eq('#general')
|
||||||
|
expect(record.filter).to eq('watch')
|
||||||
|
expect(record.category_id).to eq(category.id)
|
||||||
|
expect(record.tags).to eq([tag1.name])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates a rule when it has the same category and tags' do
|
||||||
|
existing = DiscourseChat::Rule.new({provider: 'slack',
|
||||||
|
channel: '#general',
|
||||||
|
filter: 'watch',
|
||||||
|
category_id: category.id,
|
||||||
|
tags: [tag2.name, tag1.name]
|
||||||
|
}).save!
|
||||||
|
|
||||||
|
val = DiscourseChat::Helper.smart_create_rule(provider: 'slack',
|
||||||
|
channel: '#general',
|
||||||
|
filter: 'mute',
|
||||||
|
category_id: category.id,
|
||||||
|
tags: [tag1.name, tag2.name]
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(val).to eq(:updated)
|
||||||
|
|
||||||
|
expect(DiscourseChat::Rule.all.size).to eq(1)
|
||||||
|
expect(DiscourseChat::Rule.all.first.filter).to eq('mute')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates a rule when it has the same category and filter' do
|
||||||
|
existing = DiscourseChat::Rule.new({provider: 'slack',
|
||||||
|
channel: '#general',
|
||||||
|
filter: 'watch',
|
||||||
|
category_id: category.id,
|
||||||
|
tags: [tag1.name, tag2.name]
|
||||||
|
}).save!
|
||||||
|
|
||||||
|
val = DiscourseChat::Helper.smart_create_rule(provider: 'slack',
|
||||||
|
channel: '#general',
|
||||||
|
filter: 'watch',
|
||||||
|
category_id: category.id,
|
||||||
|
tags: [tag1.name, tag3.name]
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(val).to eq(:updated)
|
||||||
|
|
||||||
|
expect(DiscourseChat::Rule.all.size).to eq(1)
|
||||||
|
expect(DiscourseChat::Rule.all.first.tags).to contain_exactly(tag1.name, tag2.name, tag3.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'destroys duplicate rules on save' do
|
||||||
|
DiscourseChat::Rule.new({provider: 'slack', channel: '#general', filter: 'watch'}).save!
|
||||||
|
DiscourseChat::Rule.new({provider: 'slack', channel: '#general', filter: 'watch'}).save!
|
||||||
|
expect(DiscourseChat::Rule.all.size).to eq(2)
|
||||||
|
val = DiscourseChat::Helper.smart_create_rule(provider: 'slack',
|
||||||
|
channel: '#general',
|
||||||
|
filter: 'watch',
|
||||||
|
category_id: nil,
|
||||||
|
tags: nil
|
||||||
|
)
|
||||||
|
expect(val).to eq(:updated)
|
||||||
|
expect(DiscourseChat::Rule.all.size).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false on error' do
|
||||||
|
val = DiscourseChat::Helper.smart_create_rule(provider: 'nonexistantprovider',
|
||||||
|
channel: '#general',
|
||||||
|
filter: 'watch',
|
||||||
|
category_id: nil,
|
||||||
|
tags: nil
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(val).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
Loading…
Reference in New Issue