banned_words 0.1.0
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.
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/README.md +24 -0
- data/Rakefile +1 -0
- data/banned_words.gemspec +24 -0
- data/lib/banned_words/core.rb +87 -0
- data/lib/banned_words/storage.rb +89 -0
- data/lib/banned_words.rb +6 -0
- data/lib/rails/generators/banned_words_generator.rb +7 -0
- data/lib/rails/generators/templates/banned_words.yml +1 -0
- data/spec/banned_words_spec.rb +4 -0
- data/spec/lib/core_spec.rb +93 -0
- data/spec/lib/storage_spec.rb +90 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/yamls/banned_words.yml +2 -0
- metadata +95 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format progress
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Banned Words
|
2
|
+
Detects and masks banned words within a text
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line in your Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'banned_words'
|
10
|
+
```
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
BannedWords.create!('dog')
|
16
|
+
phrase = 'The quick brown fox jumps over the lazy dog'
|
17
|
+
BannedWords.mask(phrase)
|
18
|
+
> 'The quick brown fox jumps over the lazy *Buzz*'
|
19
|
+
|
20
|
+
# Another example:
|
21
|
+
phrase = 'Red d-o-g'
|
22
|
+
BannedWords.mask(phrase)
|
23
|
+
> 'Red *Buzz*'
|
24
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "banned_words"
|
6
|
+
s.version = "0.1.0"
|
7
|
+
s.authors = ["Razvan Secara", "Pop Sabina"]
|
8
|
+
s.email = ["secara.razvan@yahoo.com"]
|
9
|
+
s.homepage = ""
|
10
|
+
s.summary = %q{Detects and masks banned words within a text}
|
11
|
+
s.description = %q{Detects and masks banned words within a text}
|
12
|
+
|
13
|
+
s.rubyforge_project = "banned_words"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "rails", ">= 3.0"
|
23
|
+
s.add_runtime_dependency "rails", ">= 3.0"
|
24
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "banned_words/storage"
|
2
|
+
|
3
|
+
module Core
|
4
|
+
|
5
|
+
BW_REGEX = "[^a-zA-Z0-9]*"
|
6
|
+
|
7
|
+
#
|
8
|
+
# Create a banned word. The supplied word is transformed into a banned word
|
9
|
+
# and stored into the storage file. The banned word is returned.
|
10
|
+
#
|
11
|
+
# ==== Parameters
|
12
|
+
#
|
13
|
+
# word<String>::
|
14
|
+
# Contains no more than a word.
|
15
|
+
# Returns nil if the word failed to be converted into a banned word.
|
16
|
+
#
|
17
|
+
def create!(word)
|
18
|
+
|
19
|
+
Storage::FileStore.ensure_storage_file
|
20
|
+
word = word.downcase.strip
|
21
|
+
|
22
|
+
if regexed_word = word_to_regex(word)
|
23
|
+
bw_file = Storage::FileStore.load_storage
|
24
|
+
bw_file[word] = regexed_word
|
25
|
+
Storage::FileStore.write_to_storage(bw_file)
|
26
|
+
end
|
27
|
+
|
28
|
+
regexed_word
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Masks the banned words within supplied text.
|
33
|
+
# Returns the changed text. If no banned words are found then the initial text is returned.
|
34
|
+
#
|
35
|
+
# ==== Parameters
|
36
|
+
#
|
37
|
+
# text<String>::
|
38
|
+
# The text which is checked for banned words.
|
39
|
+
# replace_with<String>::
|
40
|
+
# The word which replaces the banned words. It defaults to *Buzz*.
|
41
|
+
#
|
42
|
+
def mask(text, replace_with = "*Buzz*")
|
43
|
+
# Don't bother verifying if the text isn't present
|
44
|
+
return nil unless text.present?
|
45
|
+
|
46
|
+
if banned_words = YAML.load_file(Storage::FileStore.file_path)
|
47
|
+
bw = banned_words.values.join("|")
|
48
|
+
text.gsub!(/#{bw}/i, replace_with)
|
49
|
+
end
|
50
|
+
|
51
|
+
text
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# List the banned words. If the storage file isn't found an error is raised.
|
56
|
+
#
|
57
|
+
def list
|
58
|
+
Storage::FileStore.list_contents!
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Removes all banned words. If the storage file isn't found an error is raised.
|
63
|
+
#
|
64
|
+
def clear
|
65
|
+
Storage::FileStore.empty_storage!
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
#
|
71
|
+
# Transforms the word into a banned word. The BW_REGEX gets attached between every char.
|
72
|
+
#
|
73
|
+
def word_to_regex(word)
|
74
|
+
# Don't bother processing if the word isn't present or has more than one word
|
75
|
+
return nil if word.blank? || word[" "]
|
76
|
+
|
77
|
+
regexed_word = ""
|
78
|
+
word.chars.each_with_index do |char, i|
|
79
|
+
regexed_word += char
|
80
|
+
# Don't attach the regex after the last char.
|
81
|
+
regexed_word += BW_REGEX if i < word.size - 1
|
82
|
+
end
|
83
|
+
|
84
|
+
regexed_word
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Storage
|
2
|
+
module FileStore
|
3
|
+
extend self
|
4
|
+
|
5
|
+
#
|
6
|
+
# Retruns the path to where the banned words file source is/should be located.
|
7
|
+
#
|
8
|
+
def file_path
|
9
|
+
"#{Rails.root}/lib/banned_words.yml"
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Returns true if the banned_words.yml file exisits, false otherwise
|
14
|
+
#
|
15
|
+
def storage_exists?
|
16
|
+
File.exists?(file_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Write new data to storage. The supplied hash value will overwrite the
|
21
|
+
# exising data from the storage.
|
22
|
+
#
|
23
|
+
# ==== Parameters
|
24
|
+
#
|
25
|
+
# value<Hash>::
|
26
|
+
# Ex: {:banned_word_1 => "bw_regex_1", :banned_word_2 => "bw_regex_2"}
|
27
|
+
#
|
28
|
+
def write_to_storage(value = nil)
|
29
|
+
File.open(file_path, "w+") do |file|
|
30
|
+
YAML.dump(value, file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Returns a hash containing the banned words.
|
36
|
+
# If no banned words are present the returned has is empty.
|
37
|
+
#
|
38
|
+
def list_contents
|
39
|
+
YAML.load_file(file_path) || {}
|
40
|
+
end
|
41
|
+
alias_method :load_storage, :list_contents
|
42
|
+
|
43
|
+
#
|
44
|
+
# Returns a hash containing the banned words if the storage file exists.
|
45
|
+
# Otherwise an error is raised.
|
46
|
+
#
|
47
|
+
def list_contents!
|
48
|
+
if storage_exists?
|
49
|
+
list_contents
|
50
|
+
else
|
51
|
+
raise IOError, "No banned words file!"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Clear the storage.
|
57
|
+
#
|
58
|
+
def empty_storage
|
59
|
+
write_to_storage
|
60
|
+
end
|
61
|
+
alias_method :new_storage, :empty_storage
|
62
|
+
|
63
|
+
#
|
64
|
+
# Clear storage file if it exists.
|
65
|
+
# Otherwise an error is raised.
|
66
|
+
#
|
67
|
+
def empty_storage!
|
68
|
+
if storage_exists?
|
69
|
+
empty_storage
|
70
|
+
else
|
71
|
+
raise IOError, "No banned words file!"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Creates the storage file if it's not present
|
77
|
+
#
|
78
|
+
def ensure_storage_file
|
79
|
+
new_storage if !storage_exists?
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Mostly used in specs
|
84
|
+
#
|
85
|
+
def remove_storage_file
|
86
|
+
FileUtils.rm(file_path)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/banned_words.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
---
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Core do
|
4
|
+
let(:banned_words) { ["quick", "jumps", "dog"] }
|
5
|
+
|
6
|
+
context ".create!" do
|
7
|
+
context "with success" do
|
8
|
+
it "adds a banned word to the storage file" do
|
9
|
+
BannedWords.list.size.should == 0
|
10
|
+
BannedWords.create!("punk")
|
11
|
+
list = BannedWords.list
|
12
|
+
list.size.should == 1
|
13
|
+
list["punk"].should == "p[^a-zA-Z0-9]*u[^a-zA-Z0-9]*n[^a-zA-Z0-9]*k"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "with errors" do
|
18
|
+
it "fails to add a banned word containing more than two words" do
|
19
|
+
BannedWords.list.size.should == 0
|
20
|
+
BannedWords.create!("jack black")
|
21
|
+
BannedWords.list.size.should == 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context ".mask" do
|
27
|
+
before do
|
28
|
+
banned_words.each do |word|
|
29
|
+
BannedWords.create!(word)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "success" do
|
34
|
+
it "detects & masks one banned word - dog" do
|
35
|
+
phrase = "The dog is purple"
|
36
|
+
new_phrase = BannedWords.mask(phrase)
|
37
|
+
new_phrase.should == "The *Buzz* is purple"
|
38
|
+
new_phrase.should_not include "dog"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "detects & masks more banned words - dog, jumps, quick" do
|
42
|
+
phrase = "The quick brown fox jumps over the lazy dog"
|
43
|
+
new_phrase = BannedWords.mask(phrase)
|
44
|
+
new_phrase.should == "The *Buzz* brown fox *Buzz* over the lazy *Buzz*"
|
45
|
+
banned_words.each do |bw|
|
46
|
+
new_phrase.should_not include bw
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "no changes" do
|
52
|
+
it "cannot find any banned words" do
|
53
|
+
phrase = "Rock music records"
|
54
|
+
new_phrase = BannedWords.mask(phrase)
|
55
|
+
new_phrase.should == phrase
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
context ".list" do
|
62
|
+
it "no banned words in list" do
|
63
|
+
BannedWords.list.size.should == 0
|
64
|
+
end
|
65
|
+
|
66
|
+
it "displays 2 banned words" do
|
67
|
+
["jack", "black"].map {|word| BannedWords.create!(word)}
|
68
|
+
list = BannedWords.list
|
69
|
+
list.size.should == 2
|
70
|
+
list.keys.should == ["jack", "black"]
|
71
|
+
end
|
72
|
+
|
73
|
+
it "raises an error if the banned words file isn't found" do
|
74
|
+
Storage::FileStore.remove_storage_file
|
75
|
+
expect { BannedWords.list }.to raise_error(IOError, "No banned words file!")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context ".clear" do
|
80
|
+
it "clears the banned words list" do
|
81
|
+
BannedWords.create!("wolf")
|
82
|
+
BannedWords.list.size.should == 1
|
83
|
+
BannedWords.clear
|
84
|
+
BannedWords.list.size.should == 0
|
85
|
+
end
|
86
|
+
|
87
|
+
it "raises NoBannedWordsFile" do
|
88
|
+
Storage::FileStore.remove_storage_file
|
89
|
+
expect { BannedWords.clear }.to raise_error(IOError, "No banned words file!")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Storage::FileStore do
|
4
|
+
|
5
|
+
context ".storage_exists?" do
|
6
|
+
it "exists" do
|
7
|
+
Storage::FileStore.storage_exists?.should be_true
|
8
|
+
end
|
9
|
+
it "doesn't exist" do
|
10
|
+
Storage::FileStore.remove_storage_file
|
11
|
+
Storage::FileStore.storage_exists?.should be_false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context ".write_to_storage" do
|
16
|
+
it "writes something" do
|
17
|
+
add_and_check("something")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context ".list_contents" do
|
22
|
+
it "returns no elements" do
|
23
|
+
Storage::FileStore.list_contents.should == {}
|
24
|
+
end
|
25
|
+
it "returns one element" do
|
26
|
+
add_and_check("cat")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context ".list_contents!" do
|
31
|
+
it "returns one element" do
|
32
|
+
Storage::FileStore.write_to_storage("cat")
|
33
|
+
Storage::FileStore.list_contents!.should == "cat"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "raises IOError" do
|
37
|
+
Storage::FileStore.remove_storage_file
|
38
|
+
expect { Storage::FileStore.list_contents! }.to raise_error(IOError, "No banned words file!")
|
39
|
+
Storage::FileStore.ensure_storage_file
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context ".empty_storage" do
|
44
|
+
it "cleares all data" do
|
45
|
+
add_and_check("cat")
|
46
|
+
Storage::FileStore.empty_storage
|
47
|
+
Storage::FileStore.list_contents.should == {}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context ".empty_storage!" do
|
52
|
+
it "cleares all data" do
|
53
|
+
add_and_check("cat")
|
54
|
+
Storage::FileStore.empty_storage!
|
55
|
+
Storage::FileStore.list_contents.should == {}
|
56
|
+
end
|
57
|
+
|
58
|
+
it "raises IOError" do
|
59
|
+
Storage::FileStore.remove_storage_file
|
60
|
+
expect { Storage::FileStore.empty_storage! }.to raise_error(IOError, "No banned words file!")
|
61
|
+
Storage::FileStore.ensure_storage_file
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "aliases" do
|
66
|
+
context ".new_storage" do
|
67
|
+
it "behaves like .empty_storage with default parameter" do
|
68
|
+
["new_storage", "empty_storage"].each do |method|
|
69
|
+
add_and_check("cat")
|
70
|
+
Storage::FileStore.send(method)
|
71
|
+
Storage::FileStore.list_contents.should == {}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context ".load_storage" do
|
77
|
+
it "behaves like .list_contents" do
|
78
|
+
Storage::FileStore.write_to_storage("mouse")
|
79
|
+
Storage::FileStore.load_storage.should == Storage::FileStore.list_contents
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def add_and_check(word)
|
87
|
+
Storage::FileStore.write_to_storage(word)
|
88
|
+
Storage::FileStore.list_contents.should == word
|
89
|
+
end
|
90
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "banned_words"
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.before { stub_file_path }
|
5
|
+
config.after { clear_banned_words_file }
|
6
|
+
end
|
7
|
+
|
8
|
+
def stub_file_path
|
9
|
+
Storage::FileStore.stub(:file_path).and_return("#{File.dirname(__FILE__)}/yamls/banned_words.yml")
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear_banned_words_file
|
13
|
+
Storage::FileStore.ensure_storage_file
|
14
|
+
BannedWords.clear
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: banned_words
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Razvan Secara
|
9
|
+
- Pop Sabina
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-03-21 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
requirement: &20016960 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *20016960
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rails
|
28
|
+
requirement: &20015860 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *20015860
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rails
|
39
|
+
requirement: &20015360 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '3.0'
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *20015360
|
48
|
+
description: Detects and masks banned words within a text
|
49
|
+
email:
|
50
|
+
- secara.razvan@yahoo.com
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- .rspec
|
57
|
+
- Gemfile
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- banned_words.gemspec
|
61
|
+
- lib/banned_words.rb
|
62
|
+
- lib/banned_words/core.rb
|
63
|
+
- lib/banned_words/storage.rb
|
64
|
+
- lib/rails/generators/banned_words_generator.rb
|
65
|
+
- lib/rails/generators/templates/banned_words.yml
|
66
|
+
- spec/banned_words_spec.rb
|
67
|
+
- spec/lib/core_spec.rb
|
68
|
+
- spec/lib/storage_spec.rb
|
69
|
+
- spec/spec_helper.rb
|
70
|
+
- spec/yamls/banned_words.yml
|
71
|
+
homepage: ''
|
72
|
+
licenses: []
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project: banned_words
|
91
|
+
rubygems_version: 1.8.10
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Detects and masks banned words within a text
|
95
|
+
test_files: []
|