139 lines
4.5 KiB
Ruby
139 lines
4.5 KiB
Ruby
require 'mongoid'
|
|
# require 'mongoid/document'
|
|
|
|
module Mongoid #:nodoc:
|
|
module Validations #:nodoc:
|
|
class AssociatedValidator < ActiveModel::EachValidator
|
|
def validate_each(document, attribute, value)
|
|
values = value.is_a?(Array) ? value : [ value ]
|
|
return if values.collect { |doc| doc.nil? || doc.valid? }.all?
|
|
document.errors.add(attribute, :invalid, options.merge(:value => value)) # was causing "can't modify frozen hash"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# Mongoid causes the following warning "Collection#group no longer take a list of paramters. This usage is deprecated.Check out the new API at http://api.mongodb.org/ruby/current/Mongo/Collection.html#group-instance_method"
|
|
# it's already corrected in the mongoid master branch so waiting for the new gem to remove this patch
|
|
module Mongoid #:nodoc:
|
|
module Contexts #:nodoc:
|
|
class Mongo
|
|
def aggregate
|
|
klass.collection.group(
|
|
:key => options[:fields],
|
|
:cond => selector,
|
|
:initial => { :count => 0 },
|
|
:reduce => Javascript.aggregate
|
|
)
|
|
end
|
|
def group
|
|
klass.collection.group(
|
|
:key => options[:fields],
|
|
:cond => selector,
|
|
:initial => { :group => [] },
|
|
:reduce => Javascript.group
|
|
).collect do |docs|
|
|
docs["group"] = docs["group"].collect do |attrs|
|
|
Mongoid::Factory.build(klass, attrs)
|
|
end
|
|
docs
|
|
end
|
|
end
|
|
def grouped(start, field, reduce)
|
|
collection = klass.collection.group(
|
|
:cond => selector,
|
|
:initial => { start => "start" },
|
|
:reduce => reduce.gsub("[field]", field)
|
|
)
|
|
collection.empty? ? nil : collection.first[start.to_s]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # http://github.com/emk/mongoid/blob/503e346b1b7b250d682a12332ad9d5872f1575e6/lib/mongoid/atomicity.rb
|
|
# module Mongoid #:nodoc:
|
|
# module Atomicity #:nodoc:
|
|
# extend ActiveSupport::Concern
|
|
#
|
|
# def _updates
|
|
# processed = {}
|
|
#
|
|
# _children.inject({ "$set" => _sets, "$pushAll" => {}, :other => {} }) do |updates, child|
|
|
# changes = child._sets
|
|
# updates["$set"].update(changes)
|
|
# unless changes.empty?
|
|
# processed[child._conficting_modification_key] = true
|
|
# end
|
|
#
|
|
# # MongoDB does not allow "conflicting modifications" to be
|
|
# # performed in a single operation. Conflicting modifications are
|
|
# # detected by the 'haveConflictingMod' function in MongoDB.
|
|
# # Examination of the code suggests that two modifications (a $set
|
|
# # and a $pushAll, for example) conflict if (1) the key paths being
|
|
# # modified are equal or (2) one key path is a prefix of the other.
|
|
# # So a $set of 'addresses.0.street' will conflict with a $pushAll
|
|
# # to 'addresses', and we will need to split our update into two
|
|
# # pieces. We do not, however, attempt to match MongoDB's logic
|
|
# # exactly. Instead, we assume that two updates conflict if the
|
|
# # first component of the two key paths matches.
|
|
# if processed.has_key?(child._conficting_modification_key)
|
|
# target = :other
|
|
# else
|
|
# target = "$pushAll"
|
|
# end
|
|
#
|
|
# child._pushes.each do |attr, val|
|
|
# if updates[target].has_key?(attr)
|
|
# updates[target][attr] << val
|
|
# else
|
|
# updates[target].update({attr => [val]})
|
|
# end
|
|
# end
|
|
# updates
|
|
# end.delete_if do |key, value|
|
|
# value.empty?
|
|
# end
|
|
# end
|
|
#
|
|
# protected
|
|
# # Get the key used to check for conflicting modifications. For now, we
|
|
# # just use the first component of _path, and discard the first period
|
|
# # and everything that follows.
|
|
# def _conficting_modification_key
|
|
# _path.sub(/\..*/, '')
|
|
# end
|
|
# end
|
|
# end
|
|
|
|
|
|
# ## various patches
|
|
# module Mongoid #:nodoc:
|
|
# module Document
|
|
#
|
|
# def update_child_with_noname(child, clear = false)
|
|
# name = child.association_name
|
|
# return if name.blank? # fix a weird bug with mongoid-acts-as-tree
|
|
# update_child_without_noname(child, clear)
|
|
# end
|
|
#
|
|
# alias_method_chain :update_child, :noname
|
|
#
|
|
# # module ClassMethods
|
|
# #
|
|
# # def instantiate(attrs = nil, allocating = false) # used by carrierwave to back up the original file
|
|
# # document = super
|
|
# # document.send(:run_callbacks, :initialize) do
|
|
# # document
|
|
# # end
|
|
# # end
|
|
# #
|
|
# # end
|
|
#
|
|
# end
|
|
# end |