Module: Bible270::Mentions
- Defined in:
- lib/bible270/mentions.rb
Overview
Finding "@someone" in a reflection, and deciding who that is.
There is no username field, so mentions match against the names readers already have. Two forms are accepted, both case-insensitively:
@andrew a first name
@andrew.vonderluft first and last, joined by a dot
A mention that matches more than one reader resolves to nobody. Guessing would mean mailing the wrong person, and silence is easier to notice than a misdelivered message: the writer sees their mention unlinked.
Constant Summary collapse
- PATTERN =
Deliberately narrow: letters, digits, dots, hyphens and apostrophes, so "@andrew," and "@andrew." at the end of a sentence still work, and an email address in the body is not mistaken for a mention.
%r{(?<![\w@])@([\p{L}\p{N}][\p{L}\p{N}.'-]{0,60})}- MAX_PER_COMMENT =
10
Class Method Summary collapse
-
.extract(text) ⇒ Object
The handles written in a piece of text, normalised and de-duplicated.
-
.handles_for(first_name, last_name) ⇒ Object
Every handle a reader answers to, given their names.
-
.highlight(text) ⇒ Object
Wraps each mention so a view can style it, leaving the text otherwise untouched.
-
.normalize(handle) ⇒ Object
Trailing punctuation is dropped so "@andrew." and "@andrew" agree.
-
.preferred_handle(first_name, last_name, ambiguous: false) ⇒ Object
The form to write when there is more than one reader with the same first name: the longer handle is unambiguous.
Class Method Details
.extract(text) ⇒ Object
The handles written in a piece of text, normalised and de-duplicated.
26 27 28 29 30 31 32 33 34 |
# File 'lib/bible270/mentions.rb', line 26 def extract(text) return [] if text.nil? text.to_s.scan(PATTERN).flatten .map { |handle| normalize(handle) } .reject(&:empty?) .uniq .first(MAX_PER_COMMENT) end |
.handles_for(first_name, last_name) ⇒ Object
Every handle a reader answers to, given their names.
42 43 44 45 46 47 48 49 50 |
# File 'lib/bible270/mentions.rb', line 42 def handles_for(first_name, last_name) first = normalize(first_name) last = normalize(last_name) return [] if first.empty? handles = [first] handles << "#{first}.#{last}" unless last.empty? handles.uniq end |
.highlight(text) ⇒ Object
Wraps each mention so a view can style it, leaving the text otherwise untouched. The block receives the handle and returns the replacement.
63 64 65 66 67 68 69 70 |
# File 'lib/bible270/mentions.rb', line 63 def highlight(text) return text.to_s if text.nil? text.to_s.gsub(PATTERN) do handle = Regexp.last_match(1) yield(normalize(handle), "@#{handle}") end end |
.normalize(handle) ⇒ Object
Trailing punctuation is dropped so "@andrew." and "@andrew" agree.
37 38 39 |
# File 'lib/bible270/mentions.rb', line 37 def normalize(handle) handle.to_s.downcase.gsub(%r{[^\p{L}\p{N}.'-]}, '').sub(%r{[.'-]+\z}, '') end |
.preferred_handle(first_name, last_name, ambiguous: false) ⇒ Object
The form to write when there is more than one reader with the same first name: the longer handle is unambiguous.
54 55 56 57 58 59 |
# File 'lib/bible270/mentions.rb', line 54 def preferred_handle(first_name, last_name, ambiguous: false) handles = handles_for(first_name, last_name) return nil if handles.empty? ambiguous ? handles.last : handles.first end |