lib/mongo_adapter/adapter.rb in dm-mongo-adapter-0.2.0.pre3 vs lib/mongo_adapter/adapter.rb in dm-mongo-adapter-0.6.0
- old
+ new
@@ -1,8 +1,11 @@
module DataMapper
module Mongo
class Adapter < DataMapper::Adapters::AbstractAdapter
+ include DataMapper::Mongo::Aggregates
+ include Migrations
+
class ConnectionError < StandardError; end
# Persists one or more new resources
#
# @example
@@ -35,11 +38,11 @@
# An array of hashes to become resources
#
# @api semipublic
def read(query)
with_collection(query.model) do |collection|
- Query.new(collection, query).read
+ load_retrieved_fields!(Query.new(collection, query).read, query.model)
end
end
# Updates one or many existing resources
#
@@ -115,13 +118,31 @@
# Returns a hash where each hash key/value corresponds to a key name
# and value on the resource.
#
# @api private
def key(resource)
- resource.model.key(name).map{ |key| [key.field, key.value(resource.__send__(key.name))] }.to_hash
+ DataMapper::Ext::Array.to_hash(resource.model.key(name).map do |key|
+ [ key.field, key.dump(resource.__send__(key.name)) ]
+ end)
end
+ # TODO: document
+ def load_retrieved_fields!(fields, model)
+ fields.each do |attributes|
+ if discriminator = model.properties.discriminator
+ attributes[discriminator.field] = Class.from_mongo(attributes[discriminator.field])
+ end
+
+ attributes.each do |key, value|
+ next if discriminator && key == discriminator
+ attributes[key] = load_field_value(value)
+ end
+ end
+
+ fields
+ end
+
# Retrieves all of a records attributes and returns them as a Hash.
#
# The resulting hash can then be used with the Mongo library for
# inserting new -- and updating existing -- documents in the database.
#
@@ -140,62 +161,51 @@
attributes_from_resource(record)
when Hash
attributes_from_properties_hash(record)
end
- attributes.except('_id') unless attributes.nil?
+ attributes.delete('_id') unless attributes.nil?
+
+ attributes
end
# TODO: document
def attributes_from_resource(record)
attributes = {}
model = record.model
model.properties.each do |property|
- name = property.name
- if model.public_method_defined?(name)
- value = property.get(record)
-
- attributes[property.field] = property.custom? ?
- property.type.dump(value, property) : value
- end
+ attributes[property.field] = dump_field_value(property.dump(property.get(record)))
end
- if model.respond_to?(:embedments)
- model.embedments.each do |name, embedment|
- if model.public_method_defined?(name)
- value = record.__send__(name)
-
- if embedment.kind_of?(Embedments::OneToMany::Relationship)
- attributes[embedment.storage_name] = value.map{ |resource| attributes_as_fields(resource) }
- else
- attributes[name] = attributes_as_fields(value)
- end
- end
- end
- end
-
attributes
end
# TODO: document
def attributes_from_properties_hash(record)
attributes = {}
record.each do |key, value|
- case key
- when DataMapper::Property
- attributes[key.field] = key.custom? ? key.type.dump(value, key) : value
- when Embedments::Relationship
- attributes[key.storage_name] = attributes_as_fields(value)
- end
+ attributes[key.field] = dump_field_value(key.dump(value))
end
attributes
end
+ # TODO: document
+ def dump_field_value(value)
+ return nil if value.nil?
+ value.class.to_mongo(value)
+ end
+
+ # TODO: document
+ def load_field_value(value)
+ return nil if value.nil?
+ value.class.from_mongo(value)
+ end
+
# Runs the given block within the context of a Mongo collection.
#
# @param [Model] model
# The model whose collection is to be scoped.
#
@@ -224,15 +234,18 @@
# @api semipublic
def database
unless defined?(@database)
@database = connection.db(@options[:database])
- if @options[:username] and not @database.authenticate(
- @options[:username], @options[:password])
- raise ConnectionError,
- 'MongoDB did not recognize the given username and/or ' \
- 'password; see the server logs for more information'
+ if @options[:username]
+ begin
+ @database.authenticate(@options[:username], @options[:password])
+ rescue ::Mongo::AuthenticationError
+ raise ConnectionError,
+ 'MongoDB did not recognize the given username and/or ' \
+ 'password; see the server logs for more information'
+ end
end
end
@database
end
@@ -244,10 +257,10 @@
#
# @return [Mongo::Connection]
#
# @api semipublic
def connection
- @connection ||= ::Mongo::Connection.new(*@options.values_at(:host, :port))
+ @connection ||= ::Mongo::Connection.new(@options[:host], @options[:port], :slave_ok => true)
end
end # Adapter
end # Mongo
Adapters::MongoAdapter = DataMapper::Mongo::Adapter