Step 1 Specs
require 'rails_helper'describe String do describe "#look_spammy?" do it "should return false for a non-spam input" do expect("Jason".looks_spammy?).to be(false) expect("Fleetwood-Boldt".looks_spammy?).to be(false) expect("FLEETWOOD-BOLDT".looks_spammy?).to be(false) expect("fleetwood-boldt".looks_spammy?).to be(false) expect("John".looks_spammy?).to be(false) endit "should return true for a spam input" do expect("EpkWSQnhmoXdYCa".looks_spammy?).to be(true) expect("inRYGlPocamIVW".looks_spammy?).to be(true) expect("njOyZPVC".looks_spammy?).to be(true) expect("PwbpKimWe".looks_spammy?).to be(true) end end end
Step 1 Implementation
class String
def looks_spammy?
last_case = nil; switches = -1
self.chars.each do |c|
if last_case != :upper && /[[:upper:]]/.match(c)
switches += 1
last_case = :upper
elsif last_case != :lower && /[[:lower:]]/.match(c)
switches += 1
last_case = :lower
end
end
switches > 2
end
end
But this implementation doesn’t work for both my name “Fleetwood-Boldt” and the garbage string “njOyZPVC”
So we need to build a smarter mousetrap.
Step 2 Specs
describe "#count_upper" do
it "should return 0 for an empty string" do
expect("".count_upper).to eq(0)
end
it "should return 0 for a string with only lowercase characters" do
expect("abcdefghijk".count_upper).to eq(0)
end
it "should return 1 for a string with 1 uppercase character" do
expect("jshjXsdkfh".count_upper).to be(1)
end
it "should return 3 for a string with 3 uppercase character" do
expect("yahoo ABC xyz".count_upper).to be(3)
end
end
Step 2 Implementation
class String
def looks_spammy?
switches = -1
last_case = nil
self.chars.each do |char|
if last_case != :upper && /[[:upper:]]/.match(char)
switches += 1
last_case = :upper
elsif last_case != :lower && /[[:lower:]]/.match(char)
switches += 1
last_case = :lower
end
end
return (switches > 3) || count_upper > 2
end
def count_upper
self.gsub(/[^A-Z]/, '').length || 0
end
end
Step 3 Specs
Let’s simply abstract the ‘switches’ out into its own method and call that new method count_switches
require 'rails_helper'
describe String do
describe "#looks_spammy?" do
it "should return false for a non-spam input" do
expect("Jason".looks_spammy?).to be(false)
expect("Fleetwood-Boldt".looks_spammy?).to be(false)
expect("FLEETWOOD-BOLDT".looks_spammy?).to be(false)
expect("fleetwood-boldt".looks_spammy?).to be(false)
expect("John".looks_spammy?).to be(false)
end
it "should return true for a spam input" do
expect("EpkWSQnhmoXdYCa".looks_spammy?).to eq(true)
expect("inRYGlPocamIVW".looks_spammy?).to eq(true)
expect("njOyZPVC".looks_spammy?).to eq(true)
expect("PwbpKimWe".looks_spammy?).to eq(true)
end
end
describe "#count_switches" do
it "should return 0 for an empty string" do
expect("".count_switches).to eq(0)
end
it "should return 0 for all lowercase" do
expect("avcdefgh".count_switches).to eq(0)
end
it "should return 0 for FLEETWOOD-BOLDT" do
expect("FLEETWOOD-BOLDT".count_switches).to eq(0)
end
it "should return 3 for a string that switches 3 times" do
expect("aBcD".count_switches).to eq(3)
end
end
describe "#count_upper" do
it "should return 0 for an empty string" do
expect("".count_upper).to eq(0)
end
it "should return 0 for a string with only lowercase characters" do
expect("abcdefghijk".count_upper).to eq(0)
end
it "should return 1 for a string with 1 uppercase character" do
expect("jshjXsdkfh".count_upper).to be(1)
end
it "should return 3 for a string with 3 uppercase character" do
expect("yahoo ABC xyz".count_upper).to be(3)
end
end
end
Step 3 Implementation
class String
def looks_spammy?
return (count_switches > 3) || (count_upper > 2)
end
def count_switches
switches = -1
last_case = nil
self.chars.each do |char|
if last_case != :upper && /[[:upper:]]/.match(char)
switches += 1
last_case = :upper
elsif last_case != :lower && /[[:lower:]]/.match(char)
switches += 1
last_case = :lower
end
end
return [0,switches].max
end
def count_upper
self.gsub(/[^A-Z]/, '').length || 0
end
end
Step 4
Now I’ve inadvertantly trapped people who type their name in all uppercase, like the alternate me who types his name FLEETWOOD-BOLDT.
So our final challenge is to fix this an allow a name if it is all uppercase.
Step 4 Specs
require 'rails_helper'
describe String do
describe "#looks_spammy?" do
it "should return false for a non-spam input" do
expect("Jason".looks_spammy?).to be(false)
expect("Fleetwood-Boldt".looks_spammy?).to be(false)
expect("FLEETWOOD-BOLDT".looks_spammy?).to be(false)
expect("fleetwood-boldt".looks_spammy?).to be(false)
expect("John".looks_spammy?).to be(false)
end
it "should return true for a spam input" do
expect("EpkWSQnhmoXdYCa".looks_spammy?).to eq(true)
expect("inRYGlPocamIVW".looks_spammy?).to eq(true)
expect("njOyZPVC".looks_spammy?).to eq(true)
expect("PwbpKimWe".looks_spammy?).to eq(true)
end
end
describe "#count_switches" do
it "should return 0 for an empty string" do
expect("".count_switches).to eq(0)
end
it "should return 0 for all lowercase" do
expect("avcdefgh".count_switches).to eq(0)
end
it "should return 0 for FLEETWOOD-BOLDT" do
expect("FLEETWOOD-BOLDT".count_switches).to eq(0)
end
it "should return 3 for a string that switches 3 times" do
expect("aBcD".count_switches).to eq(3)
end
end
describe "#count_upper" do
it "should return 0 for an empty string" do
expect("".count_upper).to eq(0)
end
it "should return 0 for a string with only lowercase characters" do
expect("abcdefghijk".count_upper).to eq(0)
end
it "should return 1 for a string with 1 uppercase character" do
expect("jshjXsdkfh".count_upper).to be(1)
end
it "should return 3 for a string with 3 uppercase character" do
expect("yahoo ABC xyz".count_upper).to be(3)
end
end
describe "#all_uppercase?" do
it "should return a true of the string is all uppercase" do
expect("FLEETWOOD-BOLDT".all_uppercase?).to eq(true)
expect("JOHNSON".all_uppercase?).to eq(true)
expect("AB CD EF..G".all_uppercase?).to eq(true)
end
it "should return false if the string has any lowercase characters" do
expect("fleetwood-boldt".all_uppercase?).to eq(false)
expect("SDHFJKHDJF k".all_uppercase?).to eq(false)
end
end
end
Step 4 Implementation
class String
def looks_spammy?
return (count_switches > 3) || (count_upper > 2 && !all_uppercase?)
end
def count_switches
switches = -1
last_case = nil
self.chars.each do |char|
if last_case != :upper && /[[:upper:]]/.match(char)
switches += 1
last_case = :upper
elsif last_case != :lower && /[[:lower:]]/.match(char)
switches += 1
last_case = :lower
end
end
return [0,switches].max
end
def count_upper
self.gsub(/[^A-Z]/, '').length || 0
end
def all_uppercase?
self.upcase == self
end
end