summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2014-07-13 09:31:41 -0600
committermo khan <mo@mokhan.ca>2014-07-13 09:31:41 -0600
commitb820d323588765ed6b7f5022d1a7551cf304f51b (patch)
tree6aac3213d4c3ecba10b783d82a0f5ff685776c06
parent9d11dbbb3053811be6fd54407e08b5119c9756b3 (diff)
move classes to separate files and startto build identity map.
-rw-r--r--humble.gemspec1
-rw-r--r--lib/humble.rb2
-rw-r--r--lib/humble/column.rb3
-rw-r--r--lib/humble/default_mapper.rb16
-rw-r--r--lib/humble/identity_map.rb14
-rw-r--r--lib/humble/mapping_configuration.rb27
-rw-r--r--lib/humble/result_set.rb16
-rw-r--r--lib/humble/session.rb10
-rw-r--r--spec/integration/select_spec.rb10
9 files changed, 62 insertions, 37 deletions
diff --git a/humble.gemspec b/humble.gemspec
index e01addb..402efe6 100644
--- a/humble.gemspec
+++ b/humble.gemspec
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "rake"
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'sqlite3'
+ spec.add_development_dependency 'byebug'
end
diff --git a/lib/humble.rb b/lib/humble.rb
index eac8f9f..f4816d5 100644
--- a/lib/humble.rb
+++ b/lib/humble.rb
@@ -9,6 +9,8 @@ require "humble/mapping_configuration"
require "humble/mapping_configuration_builder"
require "humble/database_table"
require "humble/column"
+require "humble/default_mapper"
+require "humble/identity_map"
module Humble
diff --git a/lib/humble/column.rb b/lib/humble/column.rb
index 66ab233..243b17a 100644
--- a/lib/humble/column.rb
+++ b/lib/humble/column.rb
@@ -75,7 +75,8 @@ module Humble
end
def apply(row, entity, session)
- items = session.find_all(@type)
+ puts "#{@attribute} #{@type} #{row} #{entity}"
+ items = session.find_all(@type).to_a
entity.public_send("#{@attribute}=", items)
end
diff --git a/lib/humble/default_mapper.rb b/lib/humble/default_mapper.rb
new file mode 100644
index 0000000..d92f68a
--- /dev/null
+++ b/lib/humble/default_mapper.rb
@@ -0,0 +1,16 @@
+class DefaultMapper
+ attr_reader :session, :table
+
+ def initialize(table, session)
+ @table = table
+ @session = session
+ end
+
+ def map_from(row)
+ table.type.new.tap do |entity|
+ table.each do |column|
+ column.apply(row, entity, session)
+ end
+ end
+ end
+end
diff --git a/lib/humble/identity_map.rb b/lib/humble/identity_map.rb
new file mode 100644
index 0000000..b19db43
--- /dev/null
+++ b/lib/humble/identity_map.rb
@@ -0,0 +1,14 @@
+class IdentityMap
+ def initialize(items = {})
+ @items = items
+ end
+
+ def fetch(key, &block)
+ if @items.key?(key)
+ @items[key]
+ else
+ @items[key] = block.call
+ @items[key]
+ end
+ end
+end
diff --git a/lib/humble/mapping_configuration.rb b/lib/humble/mapping_configuration.rb
index f70c97b..ce5c15d 100644
--- a/lib/humble/mapping_configuration.rb
+++ b/lib/humble/mapping_configuration.rb
@@ -1,14 +1,12 @@
module Humble
class MappingConfiguration
+ attr_reader :table
+
def initialize(table, configuration)
@table = table
@configuration = configuration
end
- def find_all_using(session)
- ResultSet.new(session.create_connection[@table.name], mapper_for(session))
- end
-
def save_using(session, entity)
connection = session.create_connection[@table.name]
if primary_key.has_default_value?(entity)
@@ -29,31 +27,10 @@ module Humble
private
- def mapper_for(session)
- DefaultMapper.new(@table, session)
- end
-
def primary_key
@primary_key ||= @table.find do |column|
column.primary_key?
end
end
-
- class DefaultMapper
- attr_reader :session, :table
-
- def initialize(table, session)
- @table = table
- @session = session
- end
-
- def map_from(row)
- entity = table.type.new
- table.each do |column|
- column.apply(row, entity, session)
- end
- entity
- end
- end
end
end
diff --git a/lib/humble/result_set.rb b/lib/humble/result_set.rb
index 0a0d4ee..61e41fb 100644
--- a/lib/humble/result_set.rb
+++ b/lib/humble/result_set.rb
@@ -8,19 +8,27 @@ module Humble
end
def each(&block)
- @rows.each do |row|
- block.call(@mapper.map_from(row))
+ items.each do |item|
+ block.call(item)
end
end
def include?(item)
- self.find do |x|
+ find do |x|
x == item
end
end
def inspect
- "[#{self.map { |x| x.inspect }.join(", ")}]"
+ "[#{map { |x| x.inspect }.join(", ")}]"
+ end
+
+ private
+
+ def items
+ @items ||= @rows.map do |row|
+ @mapper.map_from(row)
+ end.to_a
end
end
end
diff --git a/lib/humble/session.rb b/lib/humble/session.rb
index 936aa39..6be422a 100644
--- a/lib/humble/session.rb
+++ b/lib/humble/session.rb
@@ -3,6 +3,7 @@ module Humble
def initialize(session_factory, configuration)
@session_factory = session_factory
@configuration = configuration
+ @identity_map = IdentityMap.new
end
def begin_transaction(&block)
@@ -16,13 +17,16 @@ module Humble
end
def find(clazz, id)
- find_all(clazz).find do |x|
- x.id == id
+ @identity_map.fetch("#{clazz.name}-#{id}") do
+ find_all(clazz).find do |x|
+ x.id == id
+ end
end
end
def find_all(clazz)
- mapping_for(clazz).find_all_using(self)
+ table = mapping_for(clazz).table
+ ResultSet.new(create_connection[table.name], DefaultMapper.new(table, self))
end
def delete(entity)
diff --git a/spec/integration/select_spec.rb b/spec/integration/select_spec.rb
index 058fb84..b06ad27 100644
--- a/spec/integration/select_spec.rb
+++ b/spec/integration/select_spec.rb
@@ -31,13 +31,11 @@ describe "select items" do
context "when fetching a single item" do
let!(:studio_id) { connection[:studios].insert(name: 'universal') }
let!(:movie_id) { connection[:movies].insert(name: 'blood in, blood out', studio_id: studio_id) }
+ let!(:review_id) { connection[:reviews].insert(movie_id: movie_id, description: description) }
+ let!(:other_review_id) { connection[:reviews].insert(movie_id: movie_id + 1, description: 'blah blah') }
let(:result) { session.find(Movie, movie_id) }
let(:description) { 'wow... that snail is fast.' }
- before :each do
- connection[:reviews].insert(movie_id: movie_id, description: description)
- end
-
it "loads the proper type" do
expect(result).to be_instance_of(Movie)
end
@@ -60,5 +58,9 @@ describe "select items" do
expect(result.reviews.first.description).to eql(description)
expect(result.reviews.first.description).to eql(description)
end
+
+ it "does not load items associated with another parent record" do
+ expect(result.reviews.find { |x| x.id == other_review_id }).to be_nil
+ end
end
end