Commit 9d11dbb
Changed files (9)
lib
spec
integration
lib/humble/column.rb
@@ -15,7 +15,8 @@ module Humble
@column_name == column_name
end
- def apply(value, entity, session)
+ def apply(row, entity, session)
+ value = row[column_name]
entity.public_send("#{@column_name}=", value)
end
@@ -51,7 +52,8 @@ module Humble
@type = type
end
- def apply(value, entity, session)
+ def apply(row, entity, session)
+ value = row[column_name]
entity.public_send("#{attribute_name}=", session.find(@type, value))
end
@@ -65,4 +67,20 @@ module Humble
column_name.to_s.gsub(/_id/, '')
end
end
+
+ class HasMany < Column
+ def initialize(attribute, type)
+ super(attribute)
+ @attribute, @type = attribute, type
+ end
+
+ def apply(row, entity, session)
+ items = session.find_all(@type)
+ entity.public_send("#{@attribute}=", items)
+ end
+
+ def prepare(entity)
+ { }
+ end
+ end
end
lib/humble/database_table.rb
@@ -32,10 +32,6 @@ module Humble
end
end
- def column_for(key)
- @columns.find { |x| x.matches?(key) }
- end
-
def prepare_statement_for(item)
@columns.inject({}) do |result, column|
result.merge(column.prepare(item))
lib/humble/mapping_configuration.rb
@@ -12,8 +12,8 @@ module Humble
def save_using(session, entity)
connection = session.create_connection[@table.name]
if primary_key.has_default_value?(entity)
- result = connection.insert(@table.prepare_statement_for(entity))
- primary_key.apply(result, entity, session)
+ connection.insert(@table.prepare_statement_for(entity))
+ primary_key.apply(connection, entity, session)
else
connection.update(@table.prepare_statement_for(entity))
end
@@ -40,17 +40,19 @@ module Humble
end
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|
- row.each do |key, value|
- @table.column_for(key).apply(value, entity, @session)
- end
+ entity = table.type.new
+ table.each do |column|
+ column.apply(row, entity, session)
end
+ entity
end
end
end
lib/humble/mapping_configuration_builder.rb
@@ -20,6 +20,10 @@ module Humble
@table.add(BelongsTo.new(foreign_key, type))
end
+ def has_many(attribute_name, type)
+ @table.add(HasMany.new(attribute_name, type))
+ end
+
def build(mapping)
@table = DatabaseTable.new
mapping.run(self)
lib/humble/session.rb
@@ -16,7 +16,9 @@ module Humble
end
def find(clazz, id)
- find_all(clazz).find { |x| x.id == id }
+ find_all(clazz).find do |x|
+ x.id == id
+ end
end
def find_all(clazz)
spec/integration/fixtures/movie_mapping.rb
@@ -1,5 +1,5 @@
class Movie
- attr_accessor :id, :name, :studio
+ attr_accessor :id, :name, :studio, :reviews
def ==(other)
return false unless other
@@ -16,5 +16,6 @@ class MovieMapping < Humble::DatabaseMapping
map.primary_key(:id, default: -1)
map.column :name
map.belongs_to :studio_id, Studio
+ map.has_many :reviews, Review
end
end
spec/integration/fixtures/review_mapping.rb
@@ -0,0 +1,13 @@
+class Review
+ attr_accessor :id, :description, :movie
+end
+
+class ReviewMapping < Humble::DatabaseMapping
+ def run(map)
+ map.table :reviews
+ map.type Review
+ map.primary_key(:id, default: -1)
+ map.column :description
+ map.belongs_to :movie_id, Movie
+ end
+end
spec/integration/select_spec.rb
@@ -5,7 +5,7 @@ describe "select items" do
context "when fetching all items" do
before :each do
- @id = connection[:movies].insert(:name => 'monsters inc')
+ @id = connection[:movies].insert(name: 'monsters inc')
end
let(:results) { session.find_all Movie }
@@ -32,6 +32,11 @@ describe "select items" 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(: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)
@@ -50,7 +55,10 @@ describe "select items" do
expect(result.studio.name).to eql('universal')
end
- xit "loads the has_many association" do
+ it "loads a has_many association" do
+ expect(result.reviews).to_not be_nil
+ expect(result.reviews.first.description).to eql(description)
+ expect(result.reviews.first.description).to eql(description)
end
end
end
spec/integration_helper.rb
@@ -2,6 +2,7 @@ require "spec_helper"
require 'sequel'
require_relative 'integration/fixtures/studio_mapping.rb'
require_relative 'integration/fixtures/movie_mapping.rb'
+require_relative 'integration/fixtures/review_mapping.rb'
shared_context "orm" do
let(:connection) { Sequel.connect(connection_string) }
@@ -22,12 +23,20 @@ shared_context "orm" do
String :name
end
+ connection.create_table :reviews do
+ primary_key :id
+ BigNum :movie_id
+ String :description
+ end
+
configuration.add(MovieMapping.new)
configuration.add(StudioMapping.new)
+ configuration.add(ReviewMapping.new)
end
after :each do
connection.drop_table :studios
connection.drop_table :movies
+ connection.drop_table :reviews
end
end