Skip to content

Commit

Permalink
Lisbn subclasses from String
Browse files Browse the repository at this point in the history
* Made method caching less obtrusive and correct if the object changes
  • Loading branch information
Mike Ragalie committed May 12, 2012
1 parent b554ede commit 9c86cf3
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 27 deletions.
1 change: 1 addition & 0 deletions lib/lisbn.rb
@@ -1,2 +1,3 @@
require "active_support/core_ext/hash"
require "lisbn/cache_method"
require "lisbn/lisbn"
15 changes: 15 additions & 0 deletions lib/lisbn/cache_method.rb
@@ -0,0 +1,15 @@
class Lisbn < String
module CacheMethod
def cache_method(*methods)
methods.map(&:to_s).each do |method|
alias_method method + "_without_cache", method
define_method method do |*args, &blk|
@cache ||= {}
@cache[[method, self]] ||= send(method + "_without_cache", *args, &blk)
end
end
end
end

extend CacheMethod
end
36 changes: 15 additions & 21 deletions lib/lisbn/lisbn.rb
@@ -1,38 +1,34 @@
class Lisbn
attr_reader :isbn

def initialize(isbn_string)
@isbn = strip(isbn_string)
class Lisbn < String
def isbn
upcase.gsub(/[^0-9X]/, '')
end

def valid?
@valid ||= begin
case isbn.length
when 10
valid_isbn_10?
when 13
valid_isbn_13?
else
false
end
case isbn.length
when 10
valid_isbn_10?
when 13
valid_isbn_13?
else
false
end
end

def isbn10
return unless valid?
return isbn if isbn.length == 10

@isbn10 ||= isbn[3..-2] + isbn_10_checksum
isbn[3..-2] + isbn_10_checksum
end

def isbn13
return unless valid?
return isbn if isbn.length == 13

@isbn13 ||= '978' + isbn[0..-2] + isbn_13_checksum
'978' + isbn[0..-2] + isbn_13_checksum
end

def split
def parts
return unless isbn13

group = prefix = nil
Expand Down Expand Up @@ -60,11 +56,9 @@ def split
[group[0..2], group[3..-1], prefix, isbn13[(group.length + prefix.length)..-2], isbn13[-1..-1]]
end

private
cache_method :isbn, :valid?, :isbn10, :isbn13, :parts

def strip(string)
string.upcase.gsub(/[^0-9X]/, '')
end
private

def isbn_10_checksum
base = isbn.length == 13 ? isbn[3..-2] : isbn[0..-2]
Expand Down
27 changes: 27 additions & 0 deletions spec/cache_method_spec.rb
@@ -0,0 +1,27 @@
require 'spec_helper'

class String
extend Lisbn::CacheMethod

def with_excitement!
self + "!"
end

cache_method :with_excitement!
end

describe "cache_method" do
subject { String.new("awesomeness") }

it "evaluates the method the first time but not subsequent times" do
subject.should_receive(:+).with("!").once.and_return("you got stubbed!")
subject.with_excitement!
subject.with_excitement!.should == "you got stubbed!"
end

it "reevaluates the method if the object's hash changes" do
subject.with_excitement!.should == "awesomeness!"
subject.replace("more awesomeness")
subject.with_excitement!.should == "more awesomeness!"
end
end
20 changes: 14 additions & 6 deletions spec/lisbn_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'

describe "Lisbn" do
describe "#initialize" do
it "converts the passed ISBN to just digits and X" do
describe "#isbn" do
it "converts the string to just digits and X" do
isbn = Lisbn.new("9487-028asdfasdf878X7")
isbn.isbn.should == "9487028878X7"
end
Expand Down Expand Up @@ -95,21 +95,29 @@
end
end

describe "#split" do
describe "#parts" do
subject { Lisbn.new("9780000000002") }

it "splits into the right groups" do
subject.split.should == ["978", "0", "00", "000000", "2"]
subject.parts.should == ["978", "0", "00", "000000", "2"]
end

it "works with long groups" do
lisbn = Lisbn.new("9786017002015")
lisbn.split.should == ["978", "601", "7002", "01", "5"]
lisbn.parts.should == ["978", "601", "7002", "01", "5"]
end

it "returns nil if it can't find a valid group" do
lisbn = Lisbn.new("9780100000002")
lisbn.split.should be_nil
lisbn.parts.should be_nil
end
end

describe "retains normal string methods" do
subject { Lisbn.new("9780000000002") }

it "#splits" do
subject.split("7").should == ["9", "80000000002"]
end
end
end

0 comments on commit 9c86cf3

Please sign in to comment.