Permalink
Browse files

Tests, plus making it testable.

  • Loading branch information...
1 parent 8868627 commit a2a0004df6d58553598264050ee8c5c8a6a77151 @infovore committed Apr 2, 2012
Showing with 158 additions and 98 deletions.
  1. +12 −97 app/models/chunk.rb
  2. +87 −0 app/models/chunk_processor.rb
  3. +2 −1 app/models/import.rb
  4. +57 −0 spec/models/chunk_spec.rb
View
@@ -1,16 +1,18 @@
class Chunk
- attr_reader :title, :author, :details, :content
+ include ChunkProcessor
+ attr_reader :title, :author, :details, :content, :processed
def initialize(chunk_string)
- lines = chunk_string.split("\n")
- title_and_author = lines.shift
-
- @title, @author = dechunk_title_and_author(title_and_author)
+ @lines = chunk_string.split("\n")
+ @processed = false
+ end
- @details = parse_details(lines.shift)
+ def process
+ @title, @author = dechunk_title_and_author(@lines[0])
+ @details = parse_details(@lines[1])
- lines.shift
- @content = lines.join
+ @content = @lines[3..@lines.size].join if @lines[3..@lines.size]
+ @processed = true
end
def method_missing(m, *args, &block)
@@ -23,11 +25,11 @@ def method_missing(m, *args, &block)
end
def is_note
- @details && details[:is_note]
+ @details && @details[:is_note]
end
def is_highlight
- @details && details[:is_highlight]
+ @details && @details[:is_highlight]
end
def self.create_from_raw_text(raw_text)
@@ -39,91 +41,4 @@ def self.create_from_raw_chunks(raw_chunks)
raw_chunks.map {|c| Chunk.new(c)}
end
- private
-
- def dechunk_title_and_author(title_and_author)
- # this needs to be sorted - add a "No Author" user on import.
- if title_and_author.match(/\((.+)\)/)
- author = title_and_author.match(/\((.+)\)/)[1]
- else
- author = nil
- end
- title = title_and_author.gsub(" (#{author})", "").strip
-
- [title, author]
- end
-
- def location_string_to_array(locations)
- start_loc, end_string = locations.split("-")
- if end_string
- i = start_loc.size - end_string.size - 1
- prefix = start_loc[0..i]
- end_loc = prefix + end_string
- [start_loc.to_i, end_loc.to_i]
- else
- [start_loc.to_i, start_loc.to_i]
- end
- end
-
- def datetime_from_string(datetime_string)
- datetime_string = datetime_string.gsub("Added on ", "").strip
- datetime = Time.parse(datetime_string)
- end
-
- def parse_details(details)
- detail_fragments = details.split("|")
- if detail_fragments.size == 3 # recently changed this from details.size. Check!
- parse_detail({:page => detail_fragments[0],
- :location => detail_fragments[1],
- :datetime => detail_fragments[2]})
- else
- parse_detail({:page => nil,
- :location => detail_fragments[0],
- :datetime => detail_fragments[1]})
- end
- end
-
- def parse_detail(detail)
- puts self.inspect
- if (detail[:page] && detail[:page].match("Note")) || detail[:location].match("Note")
- parse_note(detail)
- elsif (detail[:page] && detail[:page].match("Highlight")) || detail[:location].match("Highlight")
- parse_highlight(detail)
- end
- end
-
- def parse_note(detail)
- page, location = nil, nil
- if detail[:page]
- page = detail[:page].gsub(/\D/,"").to_i
- else
- location = detail[:location].gsub('- Note Loc. ', "").strip.to_i
- end
-
- {:is_note => true,
- :is_highlight => false,
- :page => page,
- :location => location,
- :clipped_at => datetime_from_string(detail[:datetime])}
- end
-
- def parse_highlight(detail)
- page, start_loc, end_loc = nil, nil, nil
-
- if detail[:page]
- page = detail[:page].gsub(/\D/,"").to_i
- locations = detail[:location].strip.gsub("Loc. ", "")
- start_loc, end_loc = location_string_to_array(locations)
- else
- locations = detail[:location].gsub('- Highlight Loc. ', "").strip
- start_loc, end_loc = location_string_to_array(locations)
- end
-
- {:page => page,
- :start_loc => start_loc,
- :end_loc => end_loc,
- :is_highlight => true,
- :is_note => false,
- :clipped_at => datetime_from_string(detail[:datetime])}
- end
end
@@ -0,0 +1,87 @@
+module ChunkProcessor
+ def dechunk_title_and_author(title_and_author)
+ # this needs to be sorted - add a "No Author" user on import.
+ if title_and_author.match(/\((.+)\)/)
+ author = title_and_author.match(/\((.+)\)/)[1]
+ else
+ author = nil
+ end
+ title = title_and_author.gsub(" (#{author})", "").strip
+
+ [title, author]
+ end
+
+ def location_string_to_array(locations)
+ start_loc, end_string = locations.split("-")
+ if end_string
+ i = start_loc.size - end_string.size - 1
+ prefix = start_loc[0..i]
+ end_loc = prefix + end_string
+ [start_loc.to_i, end_loc.to_i]
+ else
+ [start_loc.to_i, start_loc.to_i]
+ end
+ end
+
+ def datetime_from_string(datetime_string)
+ datetime_string = datetime_string.gsub("Added on ", "").strip
+ datetime = Time.parse(datetime_string)
+ end
+
+ def parse_details(details)
+ detail_fragments = details.split("|")
+ if detail_fragments.size == 3 # recently changed this from details.size. Check!
+ parse_detail({:page => detail_fragments[0],
+ :location => detail_fragments[1],
+ :datetime => detail_fragments[2]})
+ else
+ parse_detail({:page => nil,
+ :location => detail_fragments[0],
+ :datetime => detail_fragments[1]})
+ end
+ end
+
+ def parse_detail(detail)
+ puts self.inspect
+ if (detail[:page] && detail[:page].match("Note")) || detail[:location].match("Note")
+ parse_note(detail)
+ elsif (detail[:page] && detail[:page].match("Highlight")) || detail[:location].match("Highlight")
+ parse_highlight(detail)
+ end
+ end
+
+ def parse_note(detail)
+ page, location = nil, nil
+ if detail[:page]
+ page = detail[:page].gsub(/\D/,"").to_i
+ else
+ location = detail[:location].gsub('- Note Loc. ', "").strip.to_i
+ end
+
+ {:is_note => true,
+ :is_highlight => false,
+ :page => page,
+ :location => location,
+ :clipped_at => datetime_from_string(detail[:datetime])}
+ end
+
+ def parse_highlight(detail)
+ page, start_loc, end_loc = nil, nil, nil
+
+ if detail[:page]
+ page = detail[:page].gsub(/\D/,"").to_i
+ locations = detail[:location].strip.gsub("Loc. ", "")
+ start_loc, end_loc = location_string_to_array(locations)
+ else
+ locations = detail[:location].gsub('- Highlight Loc. ', "").strip
+ start_loc, end_loc = location_string_to_array(locations)
+ end
+
+ {:page => page,
+ :start_loc => start_loc,
+ :end_loc => end_loc,
+ :is_highlight => true,
+ :is_note => false,
+ :clipped_at => datetime_from_string(detail[:datetime])}
+ end
+end
View
@@ -17,7 +17,8 @@ def self.perform_import_from_raw_text(raw_text)
end
# now let's turn the kindle file into lots of chunks
- chunks = Chunk.create_from_raw_text(raw_text)
+ unprocessed_chunks = Chunk.create_from_raw_text(raw_text)
+ processed_chunks = unprocessed_chunks.each {|c| c.process}
# now let's walk that and find new items.
# this method returns the number of new items it found.
View
@@ -0,0 +1,57 @@
+require 'app/models/chunk_processor.rb'
+require 'app/models/chunk.rb'
+
+describe Chunk do
+ describe "when being created" do
+ it "should split a string into lines" do
+ string = stub
+ lines = stub
+ string.should_receive(:split).with("\n").and_return(lines)
+ Chunk.new(string)
+ end
+
+ it "should not be processed" do
+ Chunk.new("text").processed.should be_false
+ end
+ end
+
+ describe "being asked if it's a note" do
+ before :each do
+ @chunk = Chunk.new("string")
+ end
+
+ it "should not know if it has no details" do
+ @chunk.is_note.should be_false
+ end
+
+ it "should not be if it has details but is not a note" do
+ @chunk.instance_variable_set(:@details, nil)
+ @chunk.is_note.should be_false
+ end
+
+ it "should be if it has details and is a note" do
+ @chunk.instance_variable_set(:@details, {:is_note => true})
+ @chunk.is_note.should be_true
+ end
+ end
+
+ describe "being asked if it's a highlight" do
+ before :each do
+ @chunk = Chunk.new("string")
+ end
+
+ it "should not know if it has no details" do
+ @chunk.is_highlight.should be_false
+ end
+
+ it "should not be if it has details but is not a highlight" do
+ @chunk.instance_variable_set(:@details, {})
+ @chunk.is_highlight.should be_false
+ end
+
+ it "should be if it has details and is a highlight" do
+ @chunk.instance_variable_set(:@details, {:is_highlight => true})
+ @chunk.is_highlight.should be_true
+ end
+ end
+end

0 comments on commit a2a0004

Please sign in to comment.