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