lib/mongo_adapter/query.rb in dm-mongo-adapter-0.2.0.pre3 vs lib/mongo_adapter/query.rb in dm-mongo-adapter-0.6.0

- old
+ new

@@ -1,11 +1,11 @@ module DataMapper module Mongo # This class is responsible for taking Query instances from DataMapper and # formatting the query such that it can be performed by the Mongo library. class Query - include Extlib::Assertions + include DataMapper::Assertions include DataMapper::Query::Conditions # Creates a new Query instance # # @param [Mongo::Collection] collection @@ -40,11 +40,11 @@ def count setup_conditions_and_options # TODO: atm ruby driver doesn't support count with statements, # that's why we use find and size here as a tmp workaround - if @statements.blank? + if @statements.keys.empty? [@collection.count] else [find.size] end end @@ -66,11 +66,11 @@ keys << field.name property_names << field.name end end - if operators.blank? + if operators.empty? initial = {} reduce = JavaScript::Reduce.new.to_s finalize = nil else js_operation = JavaScript::Operation.new(operators) @@ -79,26 +79,31 @@ reduce = js_operation.reduce finalize = js_operation.finalize keys = keys - initial.keys end - - @collection.group(keys, @statements, initial, reduce, true, finalize).map do |records| - records.to_mash.symbolize_keys.only(*property_names) + + opts = { + :key => keys, :cond => @statements, :initial => initial, + :reduce => reduce, :finalize => finalize + } + + @collection.group(opts).map do |records| + DataMapper::Ext::Hash.to_mash(records).symbolize_keys end end private # TODO: document # @api private def setup_conditions_and_options @options = {} - + @options[:limit] = @query.limit if @query.limit @options[:skip] = @query.offset if @query.offset - @options[:sort] = sort_statement(@query.order) unless @query.order.empty? + @options[:sort] = sort_statement(@query.order) unless @query.order.nil? conditions_statement(@query.conditions) end # TODO: document @@ -142,20 +147,10 @@ when AndOperation then operation.each{|op| conditions_statement(op, affirmative)} when OrOperation then operation.each{|op| conditions_statement(op, affirmative)} end end - # TODO: document - # @api private - def comparison_statement_for_embedment(comparison, affirmative = true) - embedment = @query.model.embedments.values.detect { |e| e.target_model == comparison.subject.model } - - field = "#{embedment.storage_name}.#{comparison.subject.field}" - - update_statements(comparison, field, affirmative) - end - # Takes a Comparison condition and returns a Mongo-compatible hash # # @param [DataMapper::Query::Conditions::Comparison] comparison # An comparison to be made suitable for use with Mongo # @param [Boolean] affirmative @@ -168,43 +163,45 @@ def comparison_statement(comparison, affirmative = true) if comparison.relationship? return conditions_statement(comparison.foreign_key_mapping, affirmative) end - if comparison.subject.model && comparison.subject.model < EmbeddedResource - return comparison_statement_for_embedment(comparison, affirmative) - end - update_statements(comparison, comparison.subject.field, affirmative) end # TODO: document # @api private - def update_statements(comparison, field, affirmative = true) - value = comparison.value + def + update_statements(comparison, field, affirmative = true) + value = if comparison.value.kind_of?(Array) + comparison.value.map { |value| value.class.to_mongo(value) } + else + comparison.value.class.to_mongo(comparison.value) + end operator = if affirmative - case comparison - when EqualToComparison then value - when GreaterThanComparison then {'$gt' => value} - when LessThanComparison then {'$lt' => value} - when GreaterThanOrEqualToComparison then {'$gte' => value} - when LessThanOrEqualToComparison then {'$lte' => value} - when InclusionComparison then inclusion_comparison_operator(comparison, value) - when RegexpComparison then value - when LikeComparison then comparison.send(:expected) - else - raise NotImplementedError - end - else - case comparison - when EqualToComparison then {'$ne' => value} - when InclusionComparison then {'$nin' => value} - else - raise NotImplementedError - end - end + case comparison + when EqualToComparison then value + when GreaterThanComparison then {'$gt' => value} + when LessThanComparison then {'$lt' => value} + when GreaterThanOrEqualToComparison then {'$gte' => value} + when LessThanOrEqualToComparison then {'$lte' => value} + when InclusionComparison then inclusion_comparison_operator(comparison, value) + when RegexpComparison then value + when LikeComparison then comparison.send(:expected) + else + raise NotImplementedError + end + else + case comparison + when EqualToComparison then {'$ne' => value} + when InclusionComparison then {'$nin' => value} + when RegexpComparison then {'$not' => value} + else + raise NotImplementedError + end + end operator.is_a?(Hash) ? (@statements[field.to_sym] ||= {}).merge!(operator) : @statements[field.to_sym] = operator end @@ -221,10 +218,10 @@ def inclusion_comparison_operator(comparison, value) if value.kind_of?(Range) {'$gte' => value.first, value.exclude_end? ? '$lt' : '$lte' => value.last} elsif comparison.kind_of?(InclusionComparison) && value.size == 1 value.first - elsif comparison.subject.type == DataMapper::Mongo::Types::EmbeddedArray + elsif comparison.subject.kind_of?(DataMapper::Mongo::Property::Array) value else {'$in' => value} end end