friends 0.12 → 0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -3
- data/CHANGELOG.md +16 -0
- data/bin/friends +18 -16
- data/friends.gemspec +3 -2
- data/lib/friends/activity.rb +68 -34
- data/lib/friends/friend.rb +13 -6
- data/lib/friends/introvert.rb +21 -17
- data/lib/friends/version.rb +2 -1
- data/test/activity_spec.rb +48 -0
- data/test/introvert_spec.rb +6 -3
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 844eb360bcc04aed352a8b3c3371117afb18f564
|
4
|
+
data.tar.gz: db2feb8fbf5a15232b6b5923218dc8d7cff4ded1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3eb0061ba85b5dcc7eb1fa9f7d0dc1c711834b4b128b37d789252b5293b290e95de4553f55cb57a585dee1cf077e87c7b2d8fa6e5806f7ed8520227287e3e9a
|
7
|
+
data.tar.gz: cac077cacd2c4a0309b5614e1952dd65b55f0c22b7d23ed619cda4c6637f282284c0c236ff1a16ed83a4fd9ecc3bcfe434755f3c46f87c241fd8073990deda7d
|
data/.rubocop.yml
CHANGED
@@ -8,7 +8,7 @@ Alias:
|
|
8
8
|
Enabled: false
|
9
9
|
|
10
10
|
AllCops:
|
11
|
-
|
11
|
+
TargetRubyVersion: 2.3
|
12
12
|
|
13
13
|
AmbiguousOperator:
|
14
14
|
Enabled: false
|
@@ -149,6 +149,9 @@ MethodLength:
|
|
149
149
|
ModuleFunction:
|
150
150
|
Enabled: false
|
151
151
|
|
152
|
+
MutableConstant:
|
153
|
+
Enabled: true
|
154
|
+
|
152
155
|
NegatedIf:
|
153
156
|
Enabled: false
|
154
157
|
|
@@ -196,6 +199,9 @@ PredicateName:
|
|
196
199
|
Proc:
|
197
200
|
Enabled: false
|
198
201
|
|
202
|
+
Rails:
|
203
|
+
Enabled: false
|
204
|
+
|
199
205
|
RaiseArgs:
|
200
206
|
Enabled: false
|
201
207
|
|
@@ -232,8 +238,11 @@ Style/MultilineBlockChain:
|
|
232
238
|
VariableInterpolation:
|
233
239
|
Enabled: false
|
234
240
|
|
235
|
-
|
236
|
-
Enabled:
|
241
|
+
TrailingCommaInArguments:
|
242
|
+
Enabled: true
|
243
|
+
|
244
|
+
TrailingCommaInLiteral:
|
245
|
+
Enabled: true
|
237
246
|
|
238
247
|
TrivialAccessors:
|
239
248
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v0.13](https://github.com/JacobEvelyn/friends/tree/v0.13) (2016-01-21)
|
4
|
+
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.12...v0.13)
|
5
|
+
|
6
|
+
**Fixed bugs:**
|
7
|
+
|
8
|
+
- Treat double names as a single name [\#80](https://github.com/JacobEvelyn/friends/issues/80)
|
9
|
+
|
10
|
+
**Closed issues:**
|
11
|
+
|
12
|
+
- 4 RuboCop errors prevent git commit [\#78](https://github.com/JacobEvelyn/friends/issues/78)
|
13
|
+
|
14
|
+
**Merged pull requests:**
|
15
|
+
|
16
|
+
- Improve handling of double-names and names within names [\#81](https://github.com/JacobEvelyn/friends/pull/81) ([JacobEvelyn](https://github.com/JacobEvelyn))
|
17
|
+
- Update RuboCop and fix many offenses [\#79](https://github.com/JacobEvelyn/friends/pull/79) ([bloomyminded](https://github.com/bloomyminded))
|
18
|
+
|
3
19
|
## [v0.12](https://github.com/JacobEvelyn/friends/tree/v0.12) (2016-01-16)
|
4
20
|
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.11...v0.12)
|
5
21
|
|
data/bin/friends
CHANGED
@@ -24,23 +24,25 @@ subcommand_option_handling :normal
|
|
24
24
|
arguments :strict
|
25
25
|
|
26
26
|
switch [:quiet],
|
27
|
-
|
28
|
-
|
27
|
+
negatable: false,
|
28
|
+
desc: "Quiet output messages"
|
29
29
|
|
30
30
|
flag [:filename],
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
arg_name: "FILENAME",
|
32
|
+
default_value: "./friends.md",
|
33
|
+
desc: "Set the location of the friends file"
|
34
34
|
|
35
35
|
switch [:debug],
|
36
|
-
|
37
|
-
|
36
|
+
negatable: false,
|
37
|
+
desc: "Debug error messages with a full backtrace"
|
38
38
|
|
39
39
|
desc "Updates the `friends` program"
|
40
40
|
command :update do |update|
|
41
41
|
update.action do
|
42
42
|
search = `gem search friends`
|
43
|
+
# rubocop:disable Lint/AssignmentInCondition
|
43
44
|
if match = search.match(/^friends\s\(([^\)]+)\)$/)
|
45
|
+
# rubocop:enable Lint/AssignmentInCondition
|
44
46
|
remote_version = match[1]
|
45
47
|
if Semverse::Version.coerce(remote_version) >
|
46
48
|
Semverse::Version.coerce(Friends::VERSION)
|
@@ -71,9 +73,9 @@ command :list do |list|
|
|
71
73
|
list.desc "List favorite friends"
|
72
74
|
list.command :favorites do |list_favorites|
|
73
75
|
list_favorites.flag [:limit],
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
arg_name: "NUMBER",
|
77
|
+
default_value: 10,
|
78
|
+
desc: "The number of friends to return"
|
77
79
|
|
78
80
|
list_favorites.action do |_, options|
|
79
81
|
limit = options[:limit].to_i
|
@@ -95,13 +97,13 @@ command :list do |list|
|
|
95
97
|
list.desc "Lists all activities"
|
96
98
|
list.command :activities do |list_activities|
|
97
99
|
list_activities.flag [:limit],
|
98
|
-
|
99
|
-
|
100
|
-
|
100
|
+
arg_name: "NUMBER",
|
101
|
+
default_value: 10,
|
102
|
+
desc: "The number of activities to return"
|
101
103
|
|
102
104
|
list_activities.flag [:with],
|
103
|
-
|
104
|
-
|
105
|
+
arg_name: "NAME",
|
106
|
+
desc: "List only activities involving the given friend"
|
105
107
|
|
106
108
|
list_activities.action do |_, options|
|
107
109
|
limit = options[:limit].to_i
|
@@ -172,7 +174,7 @@ command :graph do |graph|
|
|
172
174
|
|
173
175
|
colors = (0...(6 * 7)).map do |n|
|
174
176
|
n *= 1.0 / 6
|
175
|
-
r = (3 * Math.sin(n
|
177
|
+
r = (3 * Math.sin(n) + 3).to_i
|
176
178
|
g = (3 * Math.sin(n + 2 * PI_3) + 3).to_i
|
177
179
|
b = (3 * Math.sin(n + 4 * PI_3) + 3).to_i
|
178
180
|
|
data/friends.gemspec
CHANGED
@@ -9,7 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Jacob Evelyn"]
|
10
10
|
spec.email = ["jacobevelyn@gmail.com"]
|
11
11
|
spec.summary = "Spend time with the people you care about."
|
12
|
-
spec.description = "Spend time with the people you care about.
|
12
|
+
spec.description = "Spend time with the people you care about. "\
|
13
|
+
"Introvert-tested. Extrovert-approved."
|
13
14
|
spec.homepage = "https://github.com/JacobEvelyn/friends"
|
14
15
|
spec.license = "MIT"
|
15
16
|
|
@@ -31,5 +32,5 @@ Gem::Specification.new do |spec|
|
|
31
32
|
spec.add_development_dependency "minitest", "~> 5.5"
|
32
33
|
spec.add_development_dependency "overcommit", "~> 0.30"
|
33
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
-
spec.add_development_dependency "rubocop", "~> 0.
|
35
|
+
spec.add_development_dependency "rubocop", "~> 0.36"
|
35
36
|
end
|
data/lib/friends/activity.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Activity represents an activity you've done with one or more Friends.
|
2
3
|
|
3
4
|
require "memoist"
|
@@ -10,11 +11,14 @@ module Friends
|
|
10
11
|
extend Serializable
|
11
12
|
extend Memoist
|
12
13
|
|
13
|
-
SERIALIZATION_PREFIX = "- "
|
14
|
+
SERIALIZATION_PREFIX = "- ".freeze
|
14
15
|
|
15
16
|
# @return [Regexp] the regex for capturing groups in deserialization
|
16
17
|
def self.deserialization_regex
|
18
|
+
# Note: this regex must be on one line because whitespace is important
|
19
|
+
# rubocop:disable Metrics/LineLength
|
17
20
|
/(#{SERIALIZATION_PREFIX})?((?<date_s>\d{4}-\d\d-\d\d)(:\s)?)?(?<description>.+)?/
|
21
|
+
# rubocop:enable Metrics/LineLength
|
18
22
|
end
|
19
23
|
|
20
24
|
# @return [Regexp] the string of what we expected during deserialization
|
@@ -37,7 +41,9 @@ module Friends
|
|
37
41
|
def display_text
|
38
42
|
date_s = Paint[date, :bold]
|
39
43
|
description_s = description.to_s
|
44
|
+
# rubocop:disable Lint/AssignmentInCondition
|
40
45
|
while match = description_s.match(/(\*\*)([^\*]+)(\*\*)/)
|
46
|
+
# rubocop:enable Lint/AssignmentInCondition
|
41
47
|
description_s = "#{match.pre_match}"\
|
42
48
|
"#{Paint[match[2], :bold, :magenta]}"\
|
43
49
|
"#{match.post_match}"
|
@@ -61,41 +67,31 @@ module Friends
|
|
61
67
|
# more information see the comments below and the
|
62
68
|
# introvert#set_likelihood_score! method.
|
63
69
|
def highlight_friends(introvert:)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# array since there may be more than one. We also iterate through the
|
69
|
-
# regexes to add the most important regexes to the hash first, so
|
70
|
-
# "Jacob Evelyn" takes precedence over all instances of "Jacob" (since
|
71
|
-
# Ruby hashes are ordered).
|
72
|
-
regex_map = Hash.new { |h, k| h[k] = [] }
|
73
|
-
while !friend_regexes.empty?
|
74
|
-
friend_regexes.each do |friend, regex_list|
|
75
|
-
regex_map[regex_list.shift] << friend
|
76
|
-
friend_regexes.delete(friend) if regex_list.empty?
|
77
|
-
end
|
78
|
-
end
|
70
|
+
# Split the regex friend map into two maps: one for names with only one
|
71
|
+
# friend match and another for ambiguous names
|
72
|
+
definite_map, ambiguous_map =
|
73
|
+
introvert.regex_friend_map.partition { |_, arr| arr.size == 1 }
|
79
74
|
|
80
75
|
matched_friends = []
|
81
76
|
|
82
|
-
# First, we find all of the
|
83
|
-
#
|
84
|
-
|
85
|
-
|
86
|
-
|
77
|
+
# First, we find all of the unambiguous matches, and make those
|
78
|
+
# substitutions.
|
79
|
+
definite_map.each do |regex, friend_list|
|
80
|
+
# If we find a match, add the friend to the matched list and replace all
|
81
|
+
# instances of the matching text with the friend's name.
|
82
|
+
description_matches(regex: regex, replace: true) do
|
87
83
|
friend = friend_list.first # There's only one friend in the list.
|
88
84
|
matched_friends << friend
|
89
|
-
|
85
|
+
friend.name
|
90
86
|
end
|
91
87
|
end
|
92
88
|
|
93
89
|
possible_matched_friends = []
|
94
90
|
|
95
91
|
# Now, we look at regex matches that are ambiguous.
|
96
|
-
|
97
|
-
|
98
|
-
|
92
|
+
ambiguous_map.each do |regex, friend_list|
|
93
|
+
# If we find a match, add the friend to the possible-match list.
|
94
|
+
description_matches(regex: regex, replace: false) do
|
99
95
|
possible_matched_friends << friend_list
|
100
96
|
end
|
101
97
|
end
|
@@ -107,21 +103,20 @@ module Friends
|
|
107
103
|
possible_matches: possible_matched_friends
|
108
104
|
)
|
109
105
|
|
110
|
-
# Now we
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
106
|
+
# Now we replace all of the ambiguous matches with our best guesses.
|
107
|
+
ambiguous_map.each do |regex, friend_list|
|
108
|
+
# If we find a match, take the most likely and replace all instances of
|
109
|
+
# the matching text with that friend's name.
|
110
|
+
description_matches(regex: regex, replace: true) do
|
111
|
+
friend_list.sort_by do |friend|
|
116
112
|
[-friend.likelihood_score, -friend.n_activities]
|
117
|
-
end.first
|
118
|
-
@description.gsub!(regex, "**#{guessed_friend.name}**")
|
113
|
+
end.first.name
|
119
114
|
end
|
120
115
|
end
|
121
116
|
|
122
117
|
# Lastly, we remove any backslashes, as these are used to escape friends'
|
123
118
|
# names that we don't want to match.
|
124
|
-
@description.delete
|
119
|
+
@description = @description.delete("\\")
|
125
120
|
end
|
126
121
|
|
127
122
|
# Updates a friend's old_name to their new_name
|
@@ -150,6 +145,45 @@ module Friends
|
|
150
145
|
|
151
146
|
private
|
152
147
|
|
148
|
+
# This method accepts a block, and tests a regex on the @description
|
149
|
+
# instance variable.
|
150
|
+
# - If the regex does not match, the block is not executed.
|
151
|
+
# - If the regex matches, the block is executed exactly once, and:
|
152
|
+
# - If `replace` is true, all of the regex's matches are replaced by the
|
153
|
+
# return value of the block, EXCEPT when the matched text is between a
|
154
|
+
# set of double-asterisks ("**") indicating it is already part of
|
155
|
+
# another friend's matched name.
|
156
|
+
# - If `replace` is not true, we do not modify @description.
|
157
|
+
# @param regex [Regexp] the regex to test against @description
|
158
|
+
# @param replace [Boolean] true iff we should replace regex matches with the
|
159
|
+
# yielded block's result in @description
|
160
|
+
def description_matches(regex:, replace:)
|
161
|
+
# rubocop:disable Lint/AssignmentInCondition
|
162
|
+
return unless match = @description.match(regex) # Abort if no match.
|
163
|
+
# rubocop:enable Lint/AssignmentInCondition
|
164
|
+
str = yield # It's important to execute the block even if not replacing.
|
165
|
+
return unless replace # Only continue if we want to replace text.
|
166
|
+
|
167
|
+
position = 0 # Prevent infinite looping by tracking last match position.
|
168
|
+
loop do
|
169
|
+
# Only make a replacement if we're not between a set of "**"s.
|
170
|
+
if match.pre_match.scan("**").size % 2 == 0 &&
|
171
|
+
match.post_match.scan("**").size % 2 == 0
|
172
|
+
@description = "#{match.pre_match}**#{str}**#{match.post_match}"
|
173
|
+
else
|
174
|
+
# If we're between double-asterisks we're already part of a name, so
|
175
|
+
# we don't make a substitution. We update `position` to avoid infinite
|
176
|
+
# looping.
|
177
|
+
position = match.end(0)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Exit when there are no more matches.
|
181
|
+
# rubocop:disable Lint/AssignmentInCondition
|
182
|
+
break unless match = @description.match(regex, position)
|
183
|
+
# rubocop:enable Lint/AssignmentInCondition
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
153
187
|
# Default sorting for an array of activities is reverse-date.
|
154
188
|
def <=>(other)
|
155
189
|
other.date <=> date
|
data/lib/friends/friend.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Friend represents a friend. You know, a real-life friend!
|
2
3
|
|
3
4
|
require "friends/serializable"
|
@@ -6,12 +7,15 @@ module Friends
|
|
6
7
|
class Friend
|
7
8
|
extend Serializable
|
8
9
|
|
9
|
-
SERIALIZATION_PREFIX = "- "
|
10
|
-
NICKNAME_PREFIX = "a.k.a. "
|
10
|
+
SERIALIZATION_PREFIX = "- ".freeze
|
11
|
+
NICKNAME_PREFIX = "a.k.a. ".freeze
|
11
12
|
|
12
13
|
# @return [Regexp] the regex for capturing groups in deserialization
|
13
14
|
def self.deserialization_regex
|
15
|
+
# Note: this regex must be on one line because whitespace is important
|
16
|
+
# rubocop:disable Metrics/LineLength
|
14
17
|
/(#{SERIALIZATION_PREFIX})?(?<name>[^\(]+)(\((?<nickname_str>#{NICKNAME_PREFIX}.+)\))?/
|
18
|
+
# rubocop:enable Metrics/LineLength
|
15
19
|
end
|
16
20
|
|
17
21
|
# @return [Regexp] the string of what we expected during deserialization
|
@@ -31,7 +35,7 @@ module Friends
|
|
31
35
|
|
32
36
|
# @return [String] the file serialization text for the friend
|
33
37
|
def serialize
|
34
|
-
"#{SERIALIZATION_PREFIX}#{
|
38
|
+
"#{SERIALIZATION_PREFIX}#{self}"
|
35
39
|
end
|
36
40
|
|
37
41
|
# @return [String] a string representing the friend's name and nicknames
|
@@ -83,13 +87,12 @@ module Friends
|
|
83
87
|
@likelihood_score || 0
|
84
88
|
end
|
85
89
|
|
86
|
-
# @return [Array] a list of all regexes to match the name in a string
|
87
|
-
# longer regexes first
|
88
|
-
# Note: for now we only match on full names or first names
|
90
|
+
# @return [Array] a list of all regexes to match the name in a string
|
89
91
|
# Example: [
|
90
92
|
# /Jacob\s+Morris\s+Evelyn/,
|
91
93
|
# /Jacob/
|
92
94
|
# ]
|
95
|
+
# NOTE: For now we only match on full names or first names.
|
93
96
|
def regexes_for_name
|
94
97
|
# We generously allow any amount of whitespace between parts of a name.
|
95
98
|
splitter = "\\s+"
|
@@ -100,6 +103,10 @@ module Friends
|
|
100
103
|
|
101
104
|
# We don't want to match names that are directly touching double asterisks
|
102
105
|
# as these are treated as sacred by our program.
|
106
|
+
# NOTE: Technically we don't need this check here, since we perform a more
|
107
|
+
# complex asterisk check in the Activity#description_matches method, but
|
108
|
+
# this class shouldn't need to know about the internal implementation of
|
109
|
+
# another class.
|
103
110
|
no_leading_asterisks = "(?<!\\*\\*)"
|
104
111
|
no_ending_asterisks = "(?!\\*\\*)"
|
105
112
|
|
data/lib/friends/introvert.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Introvert is the internal handler for the friends script. It is designed to be
|
2
3
|
# able to be used directly within another Ruby program, without needing to call
|
3
4
|
# the command-line script explicitly.
|
@@ -8,10 +9,10 @@ require "friends/friends_error"
|
|
8
9
|
|
9
10
|
module Friends
|
10
11
|
class Introvert
|
11
|
-
DEFAULT_FILENAME = "./friends.md"
|
12
|
-
ACTIVITIES_HEADER = "### Activities:"
|
13
|
-
FRIENDS_HEADER = "### Friends:"
|
14
|
-
GRAPH_DATE_FORMAT = "%b %Y" # Used as the param for date.strftime().
|
12
|
+
DEFAULT_FILENAME = "./friends.md".freeze
|
13
|
+
ACTIVITIES_HEADER = "### Activities:".freeze
|
14
|
+
FRIENDS_HEADER = "### Friends:".freeze
|
15
|
+
GRAPH_DATE_FORMAT = "%b %Y".freeze # Used as the param for date.strftime().
|
15
16
|
|
16
17
|
# @param filename [String] the name of the friends Markdown file
|
17
18
|
def initialize(filename: DEFAULT_FILENAME)
|
@@ -250,12 +251,15 @@ module Friends
|
|
250
251
|
end
|
251
252
|
end
|
252
253
|
|
253
|
-
# @return [Hash]
|
254
|
-
#
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
254
|
+
# @return [Hash] of the form { /regex/ => [list of friends matching regex] }
|
255
|
+
# This hash is sorted (because Ruby's hashes are ordered) by decreasing
|
256
|
+
# regex key length, so the key /Jacob Evelyn/ appears before /Jacob/.
|
257
|
+
def regex_friend_map
|
258
|
+
@friends.each_with_object(Hash.new { |h, k| h[k] = [] }) do |friend, hash|
|
259
|
+
friend.regexes_for_name.each do |regex|
|
260
|
+
hash[regex] << friend
|
261
|
+
end
|
262
|
+
end.sort_by { |k, _| -k.to_s.size }.to_h
|
259
263
|
end
|
260
264
|
|
261
265
|
# Sets the likelihood_score field on each friend in `possible_matches`. This
|
@@ -274,13 +278,13 @@ module Friends
|
|
274
278
|
# description, for instance, is "John Deere" vs. "John Doe"
|
275
279
|
def set_likelihood_score!(matches:, possible_matches:)
|
276
280
|
combinations = (matches + possible_matches.flatten).
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
281
|
+
combination(2).
|
282
|
+
reject do |friend1, friend2|
|
283
|
+
(matches & [friend1, friend2]).size == 2 ||
|
284
|
+
possible_matches.any? do |group|
|
285
|
+
(group & [friend1, friend2]).size == 2
|
286
|
+
end
|
287
|
+
end
|
284
288
|
|
285
289
|
@activities.each do |activity|
|
286
290
|
names = activity.friend_names
|
data/lib/friends/version.rb
CHANGED
data/test/activity_spec.rb
CHANGED
@@ -135,6 +135,54 @@ describe Friends::Activity do
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
+
describe "when one name ends another after a hyphen" do
|
139
|
+
let(:friend1) { Friends::Friend.new(name: "Mary-Kate Olsen") }
|
140
|
+
let(:friend2) { Friends::Friend.new(name: "Kate Winslet") }
|
141
|
+
let(:description) { "Shopping with Mary-Kate." }
|
142
|
+
|
143
|
+
it "gives precedence to the larger name" do
|
144
|
+
# Make sure "Kate" is a closer friend than "Mary-Kate" so we know our
|
145
|
+
# test result isn't due to chance.
|
146
|
+
friend1.n_activities = 0
|
147
|
+
friend2.n_activities = 10
|
148
|
+
|
149
|
+
subject
|
150
|
+
activity.description.must_equal "Shopping with **Mary-Kate Olsen**."
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "when one name preceeds another before a hyphen" do
|
155
|
+
let(:friend1) { Friends::Friend.new(name: "Mary-Kate Olsen") }
|
156
|
+
let(:friend2) { Friends::Friend.new(name: "Mary Poppins") }
|
157
|
+
let(:description) { "Shopping with Mary-Kate." }
|
158
|
+
|
159
|
+
it "gives precedence to the larger name" do
|
160
|
+
# Make sure "Kate" is a closer friend than "Mary-Kate" so we know our
|
161
|
+
# test result isn't due to chance.
|
162
|
+
friend1.n_activities = 0
|
163
|
+
friend2.n_activities = 10
|
164
|
+
|
165
|
+
subject
|
166
|
+
activity.description.must_equal "Shopping with **Mary-Kate Olsen**."
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "when one name is contained within another via a hyphen" do
|
171
|
+
let(:friend1) { Friends::Friend.new(name: "Mary-Jo-Kate Olsen") }
|
172
|
+
let(:friend2) { Friends::Friend.new(name: "Jo Stafford") }
|
173
|
+
let(:description) { "Shopping with Mary-Jo-Kate." }
|
174
|
+
|
175
|
+
it "gives precedence to the larger name" do
|
176
|
+
# Make sure "Kate" is a closer friend than "Mary-Kate" so we know our
|
177
|
+
# test result isn't due to chance.
|
178
|
+
friend1.n_activities = 0
|
179
|
+
friend2.n_activities = 10
|
180
|
+
|
181
|
+
subject
|
182
|
+
activity.description.must_equal "Shopping with **Mary-Jo-Kate Olsen**."
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
138
186
|
describe "when name is at end of word" do
|
139
187
|
let(:description) { "Field trip to the JimJohn Co." }
|
140
188
|
it "does not match a friend" do
|
data/test/introvert_spec.rb
CHANGED
@@ -2,8 +2,10 @@ require "./test/helper"
|
|
2
2
|
|
3
3
|
describe Friends::Introvert do
|
4
4
|
# Add readers to make internal state easier to test.
|
5
|
-
|
6
|
-
|
5
|
+
module Friends
|
6
|
+
class Introvert
|
7
|
+
attr_reader :filename, :activities, :friends
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
11
|
# Add helpers to set internal states for friends and activities.
|
@@ -318,7 +320,8 @@ describe Friends::Introvert do
|
|
318
320
|
after { File.delete(filename) if File.exists?(filename) }
|
319
321
|
|
320
322
|
it "returns the modified friend" do
|
321
|
-
friend = Friends::Friend.new(name: "Jeff",
|
323
|
+
friend = Friends::Friend.new(name: "Jeff",
|
324
|
+
nickname_str: "a.k.a. The Dude")
|
322
325
|
stub_friends([friend]) do
|
323
326
|
subject.must_equal friend
|
324
327
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: friends
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.13'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Evelyn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gli
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: '0.
|
145
|
+
version: '0.36'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: '0.
|
152
|
+
version: '0.36'
|
153
153
|
description: Spend time with the people you care about. Introvert-tested. Extrovert-approved.
|
154
154
|
email:
|
155
155
|
- jacobevelyn@gmail.com
|