friends 0.12 → 0.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|