-
-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow to respond to text in attachments #177 #180
Conversation
lib/slack-ruby-bot/commands/base.rb
Outdated
@@ -122,6 +131,23 @@ def finalize_routes! | |||
command command_name_from_class | |||
end | |||
|
|||
def match_attachments(data, route) | |||
fields_to_scan = %i[pretext text title] | |||
data.attachments_.each do |attachment| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary usage of under-bang
from Hashie::Mash
as there is a validation against missing data (data_missing?
). Will take it out.
I also thought a bit about a possibility to know which attachment record has been actually matched. Adding a new param to the block seems to be overcomplicated to me but perhaps I'm wrong.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work!
I think we need to make the attachment available inside the block as well as being able to tell what matched in the attachment (title, etc.). Eventually we can have more deliberate matching (match only title).
What do you think?
Some detailed comments below.
README.md
Outdated
|
||
```ruby | ||
class Attachment < SlackRubyBot::Bot | ||
attachment 'Slack API Documentation' do |client, data, stocks| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's stocks
here? I think what we want is to pass in the matching attachment into this block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copy-paste issue 😃will fix this, thanks
lib/slack-ruby-bot/commands/base.rb
Outdated
|
||
def data_missing?(match_method, expression, data) | ||
return true if match_method != :attachment && expression.nil? | ||
return true if match_method == :attachment && (data.attachments.nil? || data.attachments.empty?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this muddles two somewhat separate things and isn't reused elsewhere. I would actually roll this method into two next
statements above without extracting into a method or write this here as a case
statement. Either way return false
explicitly (I think currently it's nil
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take a look on this, thanks.
So how about returning a
The DSL can be extended so it takes the attachment object fields to match against. If no fields are passed, the default one will be used. |
lib/slack-ruby-bot/commands/base.rb
Outdated
) | ||
match.singleton_class.send( | ||
:define_method, :attachment_field, -> { field } | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dblock The above code adds the access to matched attachment information to the match object instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels way to complicated. You should just subclass the match object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see but subclassing a core class without a constructor doesn't seem to be less complicate. Unless there is some easy way I missed.
I think we can use
- a new class that uses delegation instead of inheritance
- a module and make the
match
object extend it on the fly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am good with a new class that uses delegation.
lib/slack-ruby-bot/commands/base.rb
Outdated
return false unless expression.nil? | ||
when :attachment | ||
return false unless data.attachments.nil? || data.attachments.empty? | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer extracting logic into methods even if they aren't re-used. Just to increase readability and reduce the cyclomatic complexity. So I decided to re-organize the method to use a case statement according to your suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something doesn't smell right here as we do the case twice, once in invoke
and once in data_missing
. Haven't tried to rewrite it, but usually this means both can be combined avoiding having to case twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is simpler :)
case match_method
when ...
expression.nil?
when :attachment
data.attachments.nil? || data.attachments.empty
else
true
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just put the checks directly in the case in invoke
but this will increase the cyclomatic complexity.
It would look like
when :match
next unless expression
# ...
when :scan
next unless expression
# ...
when :attachment
next unless data.attachments && !data.attachments.empty?
# ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a code purist re: cyclomatic complexity :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I'll add the checks to the invoke
method then :)
@dblock I implemented some of the improvements you had suggested. I pointed them as inline comments. The rest will be added soon. Let me know what you think so far. |
lib/slack-ruby-bot/commands/base.rb
Outdated
@@ -81,6 +85,11 @@ def scan(match, &block) | |||
self.routes[match] = { match_method: :scan, block: block } | |||
end | |||
|
|||
def attachment(match, &block) | |||
self.routes ||= ActiveSupport::OrderedHash.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like we need to make self.routes
a method that does @routes ||=
or something like that? We repeat this a few times. NBD
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
lib/slack-ruby-bot/commands/base.rb
Outdated
@@ -122,6 +131,36 @@ def finalize_routes! | |||
command command_name_from_class | |||
end | |||
|
|||
def match_attachments(data, route) | |||
fields_to_scan = %i[pretext text title] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this should be the third optional fields
parameter here defaulted to these. Just thinking about the future as we pass this in dynamically from the attachments
options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will think about this.
@dblock Everything is fixed. I think. Please take a look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great. I am merging this.
In next steps - we already have a support folder with things like CommandsHelper
, I think Commands::Help::Match
should just be SlackRubyBot::Commands::Match
or maybe SlackRubyBot::CommandMatch
and moved into the support folder? Maybe something else? What do you think? Maybe try a few options, potentially renaming our current CommandsHelper
class too?
@mdudzinski interested in joining the (co)maintainers of this gem? Maybe cutting the next release? If so lmk what your rubygems email is. |
@dblock Sure I'm interested -> michal[at]dudzin[dot]ski (https://rubygems.org/profiles/dudek) Yeah I don't like |
Added you, feel free to cut a release whenever you see fit. Please follow https://github.com/slack-ruby/slack-ruby-bot/blob/master/RELEASING.md. I think everything you say makes sense - play with it - try to make a PR that you can stand behind! |
@dblock Thanks! I'll do. |
Closes #177
Added a new DSL
attachment
for scanning text in attachments. This simple approach just iterates overpretext
,text
andtitle
fields of each attachment and test each field against thematch
. It returns the first match so if there is more than one attachment in the array then there is no easy way to tell which attachment record has been matched.I generated a new
.rubocop_todo.yml
file as the new offenses require a general refactoring ofSlackRubyBot::Commands::Base
class.I'll update the documentation and the changelog once this approach is accepted.