Class: Friends::Event

Inherits:
Object
  • Object
show all
Extended by:
Serializable
Defined in:
lib/friends/event.rb

Direct Known Subclasses

Activity, Note

Constant Summary collapse

SERIALIZATION_PREFIX =
"- "
DATE_PARTITION =
": "

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Serializable

deserialize

Constructor Details

#initialize(str: "") ⇒ Activity



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/friends/event.rb', line 30

def initialize(str: "")
  # Partition lets us parse "Today" and "Today: I awoke." identically.
  date_s, _, description = str.partition(DATE_PARTITION)

  time = if date_s =~ /^\d{4}-\d{2}-\d{2}$/
           Time.parse(date_s)
         else
           # If the user inputed a non YYYY-MM-DD format, asssume
           # it is in the past.
           past_time = Chronic.parse(date_s, context: :past)

           # If there's no year, Chronic will sometimes parse the date
           # as being the next occurrence of that date in the future.
           # Instead, we want to subtract one year to make it the last
           # occurrence of the date in the past.
           # NOTE: This is a hacky workaround for the fact that
           # Chronic's `context: :past` doesn't actually work. We should
           # remove this when that behavior is fixed.
           if past_time && past_time > Time.now
             Time.local(past_time.year - 1, past_time.month, past_time.day)
           else
             past_time
           end
         end

  if time
    @date = time.to_date
    @description = description
  else
    # If the user didn't input a date, we fall back to the current date.
    @date = Date.today
    @description = str # Use str in case DATE_PARTITION occurred naturally.
  end
end

Instance Attribute Details

#dateObject (readonly)

Returns the value of attribute date.



65
66
67
# File 'lib/friends/event.rb', line 65

def date
  @date
end

#descriptionObject

Returns the value of attribute description.



66
67
68
# File 'lib/friends/event.rb', line 66

def description
  @description
end

#implicit_location=(value) ⇒ Object (writeonly)

Sets the attribute implicit_location



67
68
69
# File 'lib/friends/event.rb', line 67

def implicit_location=(value)
  @implicit_location = value
end

Class Method Details

.deserialization_regexRegexp



21
22
23
# File 'lib/friends/event.rb', line 21

def self.deserialization_regex
  /(#{SERIALIZATION_PREFIX})?(?<str>.+)?/
end

Instance Method Details

#default_locationObject



141
142
143
# File 'lib/friends/event.rb', line 141

def default_location
  @default_location ||= @description[/(?<=to _)\w[^_]*(?=_)/]
end

#description_location_namesArray

Find the names of all locations in this description.



170
171
172
# File 'lib/friends/event.rb', line 170

def description_location_names
  @description.scan(/(?<=_)\w[^_]*(?=_)/).uniq
end

#friend_namesArray

Find the names of all friends in this description.



164
165
166
# File 'lib/friends/event.rb', line 164

def friend_names
  @description.scan(/(?<=\*\*)\w[^\*]*(?=\*\*)/).uniq
end

#highlight_description(introvert:) ⇒ Object

Modify the description to turn inputted friend names (e.g. “Jacob” or “Jacob Evelyn”) into full asterisk’d names (e.g. “**Jacob Evelyn**”) and inputted location names (e.g. “Atlantis”) into full underscore’d names (e.g. “Atlantis”).



106
107
108
109
# File 'lib/friends/event.rb', line 106

def highlight_description(introvert:)
  highlight_locations(introvert: introvert)
  highlight_friends(introvert: introvert)
end

#includes_friend?(friend) ⇒ Boolean



147
148
149
# File 'lib/friends/event.rb', line 147

def includes_friend?(friend)
  friend_names.include? friend.name
end

#includes_location?(location) ⇒ Boolean



137
138
139
# File 'lib/friends/event.rb', line 137

def includes_location?(location)
  location_in_description?(location) || location_is_implicit?(location)
end

#includes_tag?(tag) ⇒ Boolean



153
154
155
# File 'lib/friends/event.rb', line 153

def includes_tag?(tag)
  tags.include? tag.downcase
end

#location_namesArray



175
176
177
# File 'lib/friends/event.rb', line 175

def location_names
  @implicit_location ? [@implicit_location] : description_location_names
end

#serializeString



96
97
98
# File 'lib/friends/event.rb', line 96

def serialize
  "#{SERIALIZATION_PREFIX}#{date}: #{description}"
end

#tagsSet



158
159
160
# File 'lib/friends/event.rb', line 158

def tags
  Set.new(@description.scan(TAG_REGEX).map(&:downcase))
end

#to_sString



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/friends/event.rb', line 70

def to_s
  date_s = Paint[date, :bold]
  description_s = description.to_s
  # rubocop:disable Lint/AssignmentInCondition
  while match = description_s.match(/\*\*([^\*]+)\*\*/)
    # rubocop:enable Lint/AssignmentInCondition
    description_s = "#{match.pre_match}"\
                    "#{Paint[match[1], :bold, :magenta]}"\
                    "#{match.post_match}"
  end

  # rubocop:disable Lint/AssignmentInCondition
  while match = description_s.match(/_([^_]+)_/)
    # rubocop:enable Lint/AssignmentInCondition
    description_s = "#{match.pre_match}"\
                    "#{Paint[match[1], :bold, :yellow]}"\
                    "#{match.post_match}"
  end

  description_s = description_s.
                  gsub(TAG_REGEX, Paint['\0', :bold, :cyan])

  "#{date_s}: #{description_s}"
end

#update_friend_name(old_name:, new_name:) ⇒ String?

Updates a friend’s old_name to their new_name



116
117
118
119
120
121
# File 'lib/friends/event.rb', line 116

def update_friend_name(old_name:, new_name:)
  @description = @description.gsub(
    Regexp.new("(?<=\\*\\*)#{old_name}(?=\\*\\*)"),
    new_name
  )
end

#update_location_name(old_name:, new_name:) ⇒ String?

Updates a location’s old_name to their new_name



128
129
130
131
132
133
# File 'lib/friends/event.rb', line 128

def update_location_name(old_name:, new_name:)
  @description = @description.gsub(
    Regexp.new("(?<=_)#{old_name}(?=_)"),
    new_name
  )
end