urban_dictionary 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/lib/urban_dictionary.rb +1 -0
- data/lib/urban_dictionary/cli.rb +23 -2
- data/lib/urban_dictionary/formatters.rb +19 -4
- data/lib/urban_dictionary/version.rb +1 -1
- data/spec/spec_helper.rb +17 -14
- data/spec/urban_dictionary/cli_spec.rb +22 -13
- data/spec/urban_dictionary/formatters_spec.rb +52 -0
- data/spec/urban_dictionary/word_spec.rb +2 -2
- metadata +20 -18
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MzQxMDhhNDMxZmNlM2U1ZWUyNjI4OGNmMWEwMjkwOWRlYzQxMjhhZg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c4f3029bc9ff059717597149efd3464a53b7be3e
|
4
|
+
data.tar.gz: a4a4aaaedcd3b981d33ec34417c1026a20060a56
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MGI1ODIyZTAyN2FhODNkYjIyODhiNGQ5NWEzMmI0OTNlZGQ3Yzg4ZDA5Mzg2
|
11
|
-
Y2M3ZjQ4ZDY2ZjZlNDhjNDE4NWEyOWI2YTU0MjI2OWJkMjI2M2Y=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjZlMWZhMjA2OWMzY2NhZGI0YzFlZGRmNmIwNTA4YzNlZDQyNTFjMzAxODY0
|
14
|
-
NmZiNmJkOWU5MWI0ZDgxNjFmNTQxNzFiYTRjMTM1NDQzZTg5MTYyZDRhNzdl
|
15
|
-
MWVjZTM5ZjVmMmM3NDExOGRmMGY3MzM5ZjRkOTA2YjBhYTZhNmQ=
|
6
|
+
metadata.gz: ec7e8f36aa8631ba8cb6a5db07b4743a1353841d3d25539e3bb9af71a7605765275c2e56d8e66a53dccb66c35a286e04ff990eba99e2f514f29c8448ae9b4117
|
7
|
+
data.tar.gz: a37a3c5ea34dd959a66cc7cf977a46a86c7ae46ff7f76c70c5c3397358043d262cc9f0cd2c42000b03aa2736d4c0b5d790d13084a1f05cbf074536c186af5c96
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.1.0 - 2016-03-01
|
4
|
+
- Added support for `-n <number>` or `--definitions=<number>` to limit output
|
5
|
+
- Fixed output mangled by carriage returns (`\r`)
|
6
|
+
- Added `--format=definition` that only outputs the definitions for a word
|
7
|
+
|
3
8
|
## 1.0.0 - 2016-02-15
|
4
9
|
- Fixed broken parsing of Urban Dictionary's new layout
|
5
10
|
- Fixed bug where undefined words are displayed as the shrug emoticon (`¯\_(ツ)_/¯`)
|
data/README.md
CHANGED
@@ -45,7 +45,7 @@ Specify the output format with `--format`. The default is `plain`; `json` is als
|
|
45
45
|
"entries": [
|
46
46
|
{
|
47
47
|
"definition": "keepin it real to the fullest and super tight.",
|
48
|
-
"example": "end of the convo\
|
48
|
+
"example": "end of the convo\nLuke: aight man, peace\nQ: kool homie, keep it one hundred (100)"
|
49
49
|
},
|
50
50
|
...
|
51
51
|
}
|
data/lib/urban_dictionary.rb
CHANGED
@@ -26,5 +26,6 @@ module UrbanDictionary
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
UrbanDictionary::Formatter.register(:definition, UrbanDictionary::DefinitionFormatter)
|
29
30
|
UrbanDictionary::Formatter.register(:json, UrbanDictionary::JsonFormatter)
|
30
31
|
UrbanDictionary::Formatter.register(:plain, UrbanDictionary::PlainFormatter)
|
data/lib/urban_dictionary/cli.rb
CHANGED
@@ -68,8 +68,16 @@ module UrbanDictionary
|
|
68
68
|
options[:random] = r
|
69
69
|
end
|
70
70
|
|
71
|
+
opts.on("-n", "--definitions=NUMBER", "Limit output to the first n definitions") do |n|
|
72
|
+
options[:limit] = begin
|
73
|
+
Integer(n)
|
74
|
+
rescue ArgumentError
|
75
|
+
raise OptionParser::InvalidArgument, "#{n} is not a valid number of definitions"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
71
79
|
options[:format] = DEFAULT_FORMAT
|
72
|
-
opts.on("-f", "--format=FORMAT", "Output format (plain, json)") do |f|
|
80
|
+
opts.on("-f", "--format=FORMAT", "Output format (plain, json, definition)") do |f|
|
73
81
|
format = f.downcase.to_sym
|
74
82
|
unless UrbanDictionary::Formatter.registered.include?(format)
|
75
83
|
raise OptionParser::InvalidOption, "#{f} is not a valid format"
|
@@ -79,8 +87,17 @@ module UrbanDictionary
|
|
79
87
|
end
|
80
88
|
end
|
81
89
|
|
90
|
+
def parse
|
91
|
+
begin
|
92
|
+
options[:remaining] = option_parser.parse(@args)
|
93
|
+
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument => e
|
94
|
+
@stderr.puts e.message
|
95
|
+
exit(1)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
82
99
|
def run
|
83
|
-
|
100
|
+
parse
|
84
101
|
|
85
102
|
if options[:remaining].empty? && !options[:random]
|
86
103
|
@stdout.puts option_parser.help
|
@@ -99,6 +116,10 @@ module UrbanDictionary
|
|
99
116
|
exit(1)
|
100
117
|
end
|
101
118
|
|
119
|
+
if options[:limit]
|
120
|
+
word = UrbanDictionary::Word.new(word.word, word.entries.first(options[:limit]))
|
121
|
+
end
|
122
|
+
|
102
123
|
formatter = UrbanDictionary::Formatter.for(options[:format])
|
103
124
|
@stdout.puts(formatter.format(word))
|
104
125
|
end
|
@@ -2,6 +2,15 @@ require 'multi_json'
|
|
2
2
|
|
3
3
|
module UrbanDictionary
|
4
4
|
class Formatter
|
5
|
+
class Util
|
6
|
+
PATTERN = Regexp.compile(/\r\n|\r|\n/)
|
7
|
+
NEW_LINE = "\n"
|
8
|
+
|
9
|
+
def self.convert_linebreaks(str)
|
10
|
+
str.gsub(PATTERN, NEW_LINE)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
def self.register(name, klass)
|
6
15
|
@formatters ||= {}
|
7
16
|
if @formatters.include?(name)
|
@@ -31,9 +40,9 @@ module UrbanDictionary
|
|
31
40
|
output << '-' * word.size
|
32
41
|
output << ''
|
33
42
|
word.entries.each_with_index do |entry, i|
|
34
|
-
output << "#{i + 1}. #{entry.definition}"
|
43
|
+
output << "#{i + 1}. #{Util.convert_linebreaks(entry.definition)}"
|
35
44
|
output << ""
|
36
|
-
output << "Example: #{entry.example}"
|
45
|
+
output << "Example: #{Util.convert_linebreaks(entry.example)}"
|
37
46
|
output << ""
|
38
47
|
output << ""
|
39
48
|
end
|
@@ -41,14 +50,20 @@ module UrbanDictionary
|
|
41
50
|
end
|
42
51
|
end
|
43
52
|
|
53
|
+
class DefinitionFormatter < Formatter
|
54
|
+
def self.format(word)
|
55
|
+
word.entries.map {|ea| Util.convert_linebreaks(ea.definition) }.join("\n")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
44
59
|
class JsonFormatter < Formatter
|
45
60
|
def self.format(word)
|
46
61
|
hsh = {
|
47
62
|
:word => word.word,
|
48
63
|
:entries => word.entries.map do |entry|
|
49
64
|
{
|
50
|
-
:definition => entry.definition,
|
51
|
-
:example => entry.example
|
65
|
+
:definition => Util.convert_linebreaks(entry.definition),
|
66
|
+
:example => Util.convert_linebreaks(entry.example)
|
52
67
|
}
|
53
68
|
end
|
54
69
|
}
|
data/spec/spec_helper.rb
CHANGED
@@ -5,26 +5,23 @@ require 'shellwords'
|
|
5
5
|
require 'stringio'
|
6
6
|
require 'webmock/rspec'
|
7
7
|
|
8
|
-
|
9
|
-
config.run_all_when_everything_filtered = true
|
10
|
-
config.filter_run :focus
|
11
|
-
config.order = 'random'
|
12
|
-
end
|
13
|
-
|
14
|
-
module Test
|
15
|
-
def self.load_fixture(name)
|
16
|
-
File.read(File.expand_path("../html/#{name}", __FILE__))
|
17
|
-
end
|
18
|
-
|
8
|
+
module TestHelpers
|
19
9
|
class IO < StringIO
|
20
10
|
def content
|
21
11
|
rewind
|
22
12
|
read
|
23
13
|
end
|
14
|
+
end
|
24
15
|
|
25
|
-
|
26
|
-
|
27
|
-
|
16
|
+
def load_fixture(name)
|
17
|
+
File.read(File.expand_path("../html/#{name}", __FILE__))
|
18
|
+
end
|
19
|
+
|
20
|
+
def mk_word(term, definitions, examples)
|
21
|
+
UrbanDictionary::Word.new(
|
22
|
+
term,
|
23
|
+
Array(definitions).zip(Array(examples)).map {|ea| UrbanDictionary::Entry.new(*ea) }
|
24
|
+
)
|
28
25
|
end
|
29
26
|
end
|
30
27
|
|
@@ -35,3 +32,9 @@ class String
|
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
35
|
+
RSpec.configure do |config|
|
36
|
+
config.run_all_when_everything_filtered = true
|
37
|
+
config.filter_run :focus
|
38
|
+
config.order = 'random'
|
39
|
+
config.include TestHelpers
|
40
|
+
end
|
@@ -15,33 +15,32 @@ describe UrbanDictionary::CLI do
|
|
15
15
|
def mk_cli(str, dictionary = nil)
|
16
16
|
config = CLI::Config.new(
|
17
17
|
:args => str.to_argv,
|
18
|
-
:stdout =>
|
19
|
-
:stderr =>
|
18
|
+
:stdout => TestHelpers::IO.new,
|
19
|
+
:stderr => TestHelpers::IO.new,
|
20
20
|
)
|
21
21
|
config.update(:dictionary, dictionary) unless dictionary.nil?
|
22
22
|
cli = CLI.new(config)
|
23
23
|
[cli, config]
|
24
24
|
end
|
25
25
|
|
26
|
-
def mk_word(term, definitions, examples)
|
27
|
-
UrbanDictionary::Word.new(
|
28
|
-
term,
|
29
|
-
Array(definitions).zip(Array(examples)).map {|ea| UrbanDictionary::Entry.new(*ea) }
|
30
|
-
)
|
31
|
-
end
|
32
|
-
|
33
26
|
describe "#run" do
|
34
27
|
it "outputs help when called with no arguments" do
|
35
28
|
cli, config = mk_cli("")
|
36
29
|
cli.run
|
37
|
-
expect(config.stdout).to include("Usage: urban_dictionary")
|
30
|
+
expect(config.stdout.content).to include("Usage: urban_dictionary")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "outputs an error message when an invalid option is provided" do
|
34
|
+
cli, config = mk_cli("--invalid-option")
|
35
|
+
suppress_exit(1) { cli.run }
|
36
|
+
expect(config.stderr.content).to include("invalid option: --invalid-option")
|
38
37
|
end
|
39
38
|
|
40
39
|
it "outputs error when word has no definition" do
|
41
40
|
dictionary = double("dictionary", :define => nil)
|
42
41
|
cli, config = mk_cli("undefined word", dictionary)
|
43
42
|
suppress_exit(1) { cli.run }
|
44
|
-
expect(config.stderr).to include("No definition found for 'undefined word'")
|
43
|
+
expect(config.stderr.content).to include("No definition found for 'undefined word'")
|
45
44
|
end
|
46
45
|
|
47
46
|
it "outputs a word's definition when found" do
|
@@ -49,7 +48,7 @@ describe UrbanDictionary::CLI do
|
|
49
48
|
dictionary = double("dictionary", :define => word)
|
50
49
|
cli, config = mk_cli(word.word, dictionary)
|
51
50
|
cli.run
|
52
|
-
expect(config.stdout).to include(word.word)
|
51
|
+
expect(config.stdout.content).to include(word.word)
|
53
52
|
end
|
54
53
|
|
55
54
|
it "outputs a random word when --random is provided" do
|
@@ -57,7 +56,7 @@ describe UrbanDictionary::CLI do
|
|
57
56
|
dictionary = double("dictionary", :random_word => random_word)
|
58
57
|
cli, config = mk_cli("--random", dictionary)
|
59
58
|
cli.run
|
60
|
-
expect(config.stdout).to include(random_word.word)
|
59
|
+
expect(config.stdout.content).to include(random_word.word)
|
61
60
|
end
|
62
61
|
|
63
62
|
it "accepts --format to specify output format" do
|
@@ -68,5 +67,15 @@ describe UrbanDictionary::CLI do
|
|
68
67
|
obj = MultiJson.load(config.stdout.content)
|
69
68
|
expect(obj).to include("word" => word.word)
|
70
69
|
end
|
70
|
+
|
71
|
+
it "accepts -n to limit number of definitions" do
|
72
|
+
word = mk_word("complex word", ["def #1", "def #2", "def #3"], ["example #1", "example #2", "example #3"])
|
73
|
+
dictionary = double("dictionary", :define => word)
|
74
|
+
cli, config = mk_cli("-n 1 #{word.word}", dictionary)
|
75
|
+
cli.run
|
76
|
+
expect(config.stdout.content).to include("def #1")
|
77
|
+
expect(config.stdout.content).not_to include("def #2")
|
78
|
+
expect(config.stdout.content).not_to include("def #3")
|
79
|
+
end
|
71
80
|
end
|
72
81
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe UrbanDictionary::PlainFormatter do
|
4
|
+
let(:formatter) { UrbanDictionary::PlainFormatter }
|
5
|
+
|
6
|
+
describe "#format" do
|
7
|
+
it "converts carriage returns to new lines" do
|
8
|
+
word = mk_word("term", "definition\rwith CR", "example\rwith CR")
|
9
|
+
output = formatter.format(word)
|
10
|
+
expect(output).to include("definition\nwith CR")
|
11
|
+
expect(output).to include("example\nwith CR")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe UrbanDictionary::DefinitionFormatter do
|
17
|
+
let(:formatter) { UrbanDictionary::DefinitionFormatter }
|
18
|
+
let(:word) { mk_word("term", "definition", "example") }
|
19
|
+
|
20
|
+
describe "#format" do
|
21
|
+
it "includes the definition" do
|
22
|
+
output = formatter.format(word)
|
23
|
+
expect(output).to include(word.entries.first.definition)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "does not include the word" do
|
27
|
+
output = formatter.format(word)
|
28
|
+
expect(output).not_to include(word.word)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "does not include examples" do
|
32
|
+
output = formatter.format(word)
|
33
|
+
expect(output).not_to include(word.entries.first.example)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
describe UrbanDictionary::JsonFormatter do
|
40
|
+
let(:formatter) { UrbanDictionary::JsonFormatter }
|
41
|
+
|
42
|
+
describe "#format" do
|
43
|
+
it "converts carriage returns to new lines" do
|
44
|
+
word = mk_word("term", "definition\rwith CR", "example\rwith CR")
|
45
|
+
output = MultiJson.load(formatter.format(word))
|
46
|
+
expected_output = [
|
47
|
+
{"definition" => "definition\nwith CR", "example" => "example\nwith CR"}
|
48
|
+
]
|
49
|
+
expect(output["entries"]).to eq(expected_output)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -24,8 +24,8 @@ describe UrbanDictionary::Word do
|
|
24
24
|
describe "class method" do
|
25
25
|
describe "#from_url" do
|
26
26
|
let(:url){ "the_url" }
|
27
|
-
let(:html_with_results){
|
28
|
-
let(:html_without_results){
|
27
|
+
let(:html_with_results){ load_fixture("on_fleek_2016-02-15.html") }
|
28
|
+
let(:html_without_results){ load_fixture("sisyphus_2016-02-15.html") }
|
29
29
|
|
30
30
|
it "parses a valid word" do
|
31
31
|
word = UrbanDictionary::Word.from_html(html_with_results)
|
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: urban_dictionary
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Greenberg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02
|
11
|
+
date: 2016-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: multi_json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '3.4'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.4'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: webmock
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 1.22.6
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.22.6
|
83
83
|
description: Interface to urbandictionary.com
|
@@ -88,9 +88,9 @@ executables:
|
|
88
88
|
extensions: []
|
89
89
|
extra_rdoc_files: []
|
90
90
|
files:
|
91
|
-
- .gitignore
|
92
|
-
- .rspec
|
93
|
-
- .travis.yml
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rspec"
|
93
|
+
- ".travis.yml"
|
94
94
|
- CHANGELOG.md
|
95
95
|
- Gemfile
|
96
96
|
- LICENSE.md
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- spec/spec_helper.rb
|
112
112
|
- spec/urban_dictionary/cli_spec.rb
|
113
113
|
- spec/urban_dictionary/entry_spec.rb
|
114
|
+
- spec/urban_dictionary/formatters_spec.rb
|
114
115
|
- spec/urban_dictionary/word_spec.rb
|
115
116
|
- spec/urban_dictionary_spec.rb
|
116
117
|
- urban_dictionary.gemspec
|
@@ -123,17 +124,17 @@ require_paths:
|
|
123
124
|
- lib
|
124
125
|
required_ruby_version: !ruby/object:Gem::Requirement
|
125
126
|
requirements:
|
126
|
-
- -
|
127
|
+
- - ">="
|
127
128
|
- !ruby/object:Gem::Version
|
128
129
|
version: '0'
|
129
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
131
|
requirements:
|
131
|
-
- -
|
132
|
+
- - ">="
|
132
133
|
- !ruby/object:Gem::Version
|
133
134
|
version: '0'
|
134
135
|
requirements: []
|
135
136
|
rubyforge_project: urban_dictionary
|
136
|
-
rubygems_version: 2.5
|
137
|
+
rubygems_version: 2.4.5
|
137
138
|
signing_key:
|
138
139
|
specification_version: 4
|
139
140
|
summary: Interface to urbandictionary.com
|
@@ -146,5 +147,6 @@ test_files:
|
|
146
147
|
- spec/spec_helper.rb
|
147
148
|
- spec/urban_dictionary/cli_spec.rb
|
148
149
|
- spec/urban_dictionary/entry_spec.rb
|
150
|
+
- spec/urban_dictionary/formatters_spec.rb
|
149
151
|
- spec/urban_dictionary/word_spec.rb
|
150
152
|
- spec/urban_dictionary_spec.rb
|