looks_spammy?

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)
      end
      it "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