lookout-mongo_mapper 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/UPGRADES +26 -0
- data/bin/mmconsole +59 -0
- data/examples/attr_accessible.rb +22 -0
- data/examples/attr_protected.rb +22 -0
- data/examples/cache_key.rb +24 -0
- data/examples/custom_types.rb +24 -0
- data/examples/identity_map.rb +33 -0
- data/examples/identity_map/automatic.rb +2 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +38 -0
- data/examples/querying.rb +35 -0
- data/examples/safe.rb +43 -0
- data/examples/scopes.rb +52 -0
- data/examples/validating/embedded_docs.rb +29 -0
- data/lib/mongo_mapper.rb +94 -0
- data/lib/mongo_mapper/connection.rb +96 -0
- data/lib/mongo_mapper/document.rb +42 -0
- data/lib/mongo_mapper/embedded_document.rb +32 -0
- data/lib/mongo_mapper/exceptions.rb +30 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +26 -0
- data/lib/mongo_mapper/extensions/object_id.rb +32 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +28 -0
- data/lib/mongo_mapper/locale/en.yml +5 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +22 -0
- data/lib/mongo_mapper/plugins/accessible.rb +52 -0
- data/lib/mongo_mapper/plugins/active_model.rb +18 -0
- data/lib/mongo_mapper/plugins/associations.rb +90 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
- data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
- data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
- data/lib/mongo_mapper/plugins/clone.rb +22 -0
- data/lib/mongo_mapper/plugins/dirty.rb +60 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +13 -0
- data/lib/mongo_mapper/plugins/inspect.rb +16 -0
- data/lib/mongo_mapper/plugins/keys.rb +313 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
- data/lib/mongo_mapper/plugins/pagination.rb +16 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/querying.rb +165 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +36 -0
- data/lib/mongo_mapper/plugins/scopes.rb +27 -0
- data/lib/mongo_mapper/plugins/serialization.rb +109 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/touch.rb +18 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
- data/lib/mongo_mapper/plugins/validations.rb +86 -0
- data/lib/mongo_mapper/railtie.rb +48 -0
- data/lib/mongo_mapper/railtie/database.rake +65 -0
- data/lib/mongo_mapper/translation.rb +10 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
- data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
- data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
- data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -0
- data/test/_NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +238 -0
- data/test/functional/associations/test_in_array_proxy.rb +349 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
- data/test/functional/associations/test_many_documents_proxy.rb +866 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
- data/test/functional/associations/test_one_as_proxy.rb +491 -0
- data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
- data/test/functional/associations/test_one_proxy.rb +383 -0
- data/test/functional/test_accessible.rb +198 -0
- data/test/functional/test_associations.rb +46 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +77 -0
- data/test/functional/test_callbacks.rb +232 -0
- data/test/functional/test_dirty.rb +301 -0
- data/test/functional/test_document.rb +282 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +288 -0
- data/test/functional/test_equality.rb +20 -0
- data/test/functional/test_identity_map.rb +513 -0
- data/test/functional/test_indexes.rb +50 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +537 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +201 -0
- data/test/functional/test_querying.rb +935 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +240 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_touch.rb +125 -0
- data/test/functional/test_userstamps.rb +44 -0
- data/test/functional/test_validations.rb +414 -0
- data/test/models.rb +261 -0
- data/test/support/railtie.rb +4 -0
- data/test/support/railtie/autoloaded.rb +2 -0
- data/test/support/railtie/not_autoloaded.rb +3 -0
- data/test/support/railtie/parent.rb +3 -0
- data/test/test_active_model_lint.rb +18 -0
- data/test/test_helper.rb +93 -0
- data/test/unit/associations/test_base.rb +146 -0
- data/test/unit/associations/test_belongs_to_association.rb +29 -0
- data/test/unit/associations/test_many_association.rb +63 -0
- data/test/unit/associations/test_one_association.rb +47 -0
- data/test/unit/associations/test_proxy.rb +100 -0
- data/test/unit/serializers/test_json_serializer.rb +216 -0
- data/test/unit/serializers/test_xml_serializer.rb +196 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_document.rb +249 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +682 -0
- data/test/unit/test_equality.rb +38 -0
- data/test/unit/test_exceptions.rb +12 -0
- data/test/unit/test_extensions.rb +380 -0
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +47 -0
- data/test/unit/test_key.rb +205 -0
- data/test/unit/test_keys.rb +65 -0
- data/test/unit/test_mongo_mapper.rb +143 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +89 -0
- data/test/unit/test_rails.rb +183 -0
- data/test/unit/test_rails_compatibility.rb +38 -0
- data/test/unit/test_rails_reflect_on_association.rb +118 -0
- data/test/unit/test_railtie.rb +66 -0
- data/test/unit/test_serialization.rb +166 -0
- data/test/unit/test_time_zones.rb +44 -0
- data/test/unit/test_translation.rb +27 -0
- data/test/unit/test_validations.rb +562 -0
- metadata +285 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Querying
|
|
5
|
+
Methods = Plucky::Methods + [:find!]
|
|
6
|
+
|
|
7
|
+
module Decorator
|
|
8
|
+
include DynamicQuerying::ClassMethods
|
|
9
|
+
|
|
10
|
+
def model(model=nil)
|
|
11
|
+
return @model if model.nil?
|
|
12
|
+
@model = model
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def find!(*ids)
|
|
17
|
+
raise DocumentNotFound, "Couldn't find without an ID" if ids.size == 0
|
|
18
|
+
|
|
19
|
+
find(*ids).tap do |result|
|
|
20
|
+
if result.nil? || ids.size != Array(result).size
|
|
21
|
+
raise DocumentNotFound, "Couldn't find all of the ids (#{ids.join(',')}). Found #{Array(result).size}, but was expecting #{ids.size}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def method_missing(method, *args, &block)
|
|
28
|
+
return super unless model.respond_to?(method)
|
|
29
|
+
result = model.send(method, *args, &block)
|
|
30
|
+
return super unless result.is_a?(Plucky::Query)
|
|
31
|
+
merge(result)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Rails
|
|
5
|
+
autoload :ActiveRecordAssociationAdapter, "mongo_mapper/plugins/rails/active_record_association_adapter"
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
def to_param
|
|
9
|
+
id.to_s if persisted?
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_model
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_key
|
|
17
|
+
[id] if persisted?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def new_record?
|
|
21
|
+
new?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def read_attribute(name)
|
|
25
|
+
self[name]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def read_attribute_before_type_cast(name)
|
|
29
|
+
read_key_before_type_cast(name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def write_attribute(name, value)
|
|
33
|
+
self[name] = value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module ClassMethods
|
|
37
|
+
def has_one(*args)
|
|
38
|
+
one(*args)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def has_many(*args, &extension)
|
|
42
|
+
many(*args, &extension)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def column_names
|
|
46
|
+
keys.keys
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns returns an ActiveRecordAssociationAdapter for an association. This adapter has an API that is a
|
|
50
|
+
# subset of ActiveRecord::Reflection::AssociationReflection. This allows MongoMapper to be used with the
|
|
51
|
+
# association helpers in gems like simple_form and formtastic.
|
|
52
|
+
def reflect_on_association(name)
|
|
53
|
+
ActiveRecordAssociationAdapter.for_association(associations[name]) if associations[name]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Rails
|
|
5
|
+
class ActiveRecordAssociationAdapter
|
|
6
|
+
attr_reader :klass, :macro, :name, :options
|
|
7
|
+
|
|
8
|
+
def self.for_association(association)
|
|
9
|
+
macro = case association
|
|
10
|
+
when MongoMapper::Plugins::Associations::BelongsToAssociation
|
|
11
|
+
:belongs_to
|
|
12
|
+
when MongoMapper::Plugins::Associations::ManyAssociation
|
|
13
|
+
:has_many
|
|
14
|
+
when MongoMapper::Plugins::Associations::OneAssociation
|
|
15
|
+
:has_one
|
|
16
|
+
else
|
|
17
|
+
raise "no #{name} for association of type #{association.class}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
new(association, macro)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def initialize(association, macro)
|
|
24
|
+
@klass, @name = association.klass, association.name
|
|
25
|
+
# only include compatible options
|
|
26
|
+
@options = association.options.slice(:conditions, :order)
|
|
27
|
+
|
|
28
|
+
@macro = macro
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Safe
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def inherited(subclass)
|
|
9
|
+
super
|
|
10
|
+
subclass.safe if safe?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def safe
|
|
14
|
+
@safe = true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def safe?
|
|
18
|
+
@safe == true
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def save_to_collection(options={})
|
|
23
|
+
options[:safe] = self.class.safe? unless options.key?(:safe)
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Sci
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
extend ActiveSupport::DescendantsTracker
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
def inherited(subclass)
|
|
13
|
+
key :_type, String unless key?(:_type)
|
|
14
|
+
subclass.instance_variable_set("@single_collection_inherited", true)
|
|
15
|
+
subclass.set_collection_name(collection_name) unless subclass.embeddable?
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def single_collection_inherited?
|
|
20
|
+
@single_collection_inherited == true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def query(options={})
|
|
24
|
+
super.tap do |query|
|
|
25
|
+
query[:_type] = {'$in' => [name] + descendants.map(&:name)} if single_collection_inherited?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(*args)
|
|
31
|
+
super
|
|
32
|
+
write_key :_type, self.class.name if self.class.key?(:_type)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Scopes
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
class_attribute :_scopes
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
def scope(name, scope_options={})
|
|
13
|
+
scopes[name] = lambda do |*args|
|
|
14
|
+
result = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options
|
|
15
|
+
result = self.query(result) if result.is_a?(Hash)
|
|
16
|
+
self.query.merge(result)
|
|
17
|
+
end
|
|
18
|
+
singleton_class.send :define_method, name, &scopes[name]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def scopes
|
|
22
|
+
self._scopes || self._scopes = {}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'active_model/serializers/json'
|
|
3
|
+
require 'active_model/serializers/xml'
|
|
4
|
+
|
|
5
|
+
module MongoMapper
|
|
6
|
+
module Plugins
|
|
7
|
+
module Serialization
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
include ::ActiveModel::Serializers::JSON
|
|
12
|
+
include ::ActiveModel::Serializers::Xml
|
|
13
|
+
self.include_root_in_json = false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def serializable_attributes
|
|
17
|
+
attributes.keys.map { |k| k.to_s } + ['id'] - ['_id']
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serializable_hash(options = nil)
|
|
21
|
+
options ||= {}
|
|
22
|
+
|
|
23
|
+
options[:only] = Array.wrap(options[:only]).map { |k| k.to_s }
|
|
24
|
+
options[:except] = Array.wrap(options[:except]).map { |k| k.to_s }
|
|
25
|
+
|
|
26
|
+
attribute_names = serializable_attributes
|
|
27
|
+
|
|
28
|
+
if options[:only].any?
|
|
29
|
+
attribute_names &= options[:only]
|
|
30
|
+
elsif options[:except].any?
|
|
31
|
+
attribute_names -= options[:except]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
attribute_names += Array.wrap(options[:methods]).map { |m| m.to_s }.select do |method|
|
|
35
|
+
respond_to?(method)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
hash = attribute_names.sort.inject({}) do |hash, name|
|
|
39
|
+
value = send(name)
|
|
40
|
+
hash[name] = if value.is_a?(Array)
|
|
41
|
+
value.map {|v| v.respond_to?(:serializable_hash) ? v.serializable_hash : v }
|
|
42
|
+
elsif value.respond_to?(:serializable_hash)
|
|
43
|
+
value.serializable_hash
|
|
44
|
+
else
|
|
45
|
+
value
|
|
46
|
+
end
|
|
47
|
+
hash
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
serializable_add_includes(options) do |association, records, opts|
|
|
51
|
+
hash[association.to_s] = records.is_a?(Array) ?
|
|
52
|
+
records.map { |r| r.serializable_hash(opts) } :
|
|
53
|
+
records.serializable_hash(opts)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
hash
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_xml(options = {}, &block)
|
|
60
|
+
XmlSerializer.new(self, options).serialize(&block)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def serializable_add_includes(options = {})
|
|
66
|
+
return unless include_associations = options.delete(:include)
|
|
67
|
+
|
|
68
|
+
base_only_or_except = { :except => options[:except],
|
|
69
|
+
:only => options[:only] }
|
|
70
|
+
|
|
71
|
+
include_has_options = include_associations.is_a?(Hash)
|
|
72
|
+
associations = include_has_options ? include_associations.keys : Array.wrap(include_associations)
|
|
73
|
+
|
|
74
|
+
associations.each do |association|
|
|
75
|
+
records = get_proxy(self.class.associations[association])
|
|
76
|
+
unless records.nil?
|
|
77
|
+
association_options = include_has_options ? include_associations[association] : base_only_or_except
|
|
78
|
+
opts = options.merge(association_options)
|
|
79
|
+
yield(association, records, opts)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
options[:include] = include_associations
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
module ClassMethods
|
|
87
|
+
def from_json(json)
|
|
88
|
+
self.new.from_json(json)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def from_xml(xml)
|
|
92
|
+
self.new.from_xml(xml)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Override default Serializer to use #serializable_hash
|
|
98
|
+
class XmlSerializer < ::ActiveModel::Serializers::Xml::Serializer
|
|
99
|
+
def attributes_hash
|
|
100
|
+
@serializable.serializable_hash(options)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def serializable_methods
|
|
104
|
+
# Methods are already included in #serializable_hash
|
|
105
|
+
[]
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Timestamps
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def timestamps!
|
|
9
|
+
key :created_at, Time
|
|
10
|
+
key :updated_at, Time
|
|
11
|
+
class_eval { before_save :update_timestamps }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def update_timestamps
|
|
16
|
+
now = Time.now.utc
|
|
17
|
+
self[:created_at] = now if !persisted? && !created_at?
|
|
18
|
+
self[:updated_at] = now
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module MongoMapper
|
|
2
|
+
module Plugins
|
|
3
|
+
module Touch
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
def touch(key = :updated_at)
|
|
7
|
+
raise ArgumentError, "Invalid key named #{key}" unless self.key_names.include?(key.to_s)
|
|
8
|
+
if self.class.embeddable?
|
|
9
|
+
self.write_attribute(key, Time.now.utc)
|
|
10
|
+
self._parent_document.touch
|
|
11
|
+
else
|
|
12
|
+
self.set(key => Time.now.utc)
|
|
13
|
+
end
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Userstamps
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def userstamps!(options = {})
|
|
9
|
+
class_name = (options[:class_name] || options[:class] || 'User' ).to_s
|
|
10
|
+
key :creator_id, ObjectId
|
|
11
|
+
key :updater_id, ObjectId
|
|
12
|
+
belongs_to :creator, :class_name => class_name
|
|
13
|
+
belongs_to :updater, :class_name => class_name
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Validations
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
include ::ActiveModel::Validations
|
|
8
|
+
include ::ActiveModel::Validations::Callbacks
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
def validates_uniqueness_of(*attr_names)
|
|
12
|
+
validates_with UniquenessValidator, _merge_attributes(attr_names)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def validates_associated(*attr_names)
|
|
16
|
+
validates_with AssociatedValidator, _merge_attributes(attr_names)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def save(options = {})
|
|
21
|
+
options.reverse_merge!(:validate => true)
|
|
22
|
+
!options[:validate] || valid? ? super : false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def valid?(context = nil)
|
|
26
|
+
context ||= (new_record? ? :create : :update)
|
|
27
|
+
super(context)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class UniquenessValidator < ::ActiveModel::EachValidator
|
|
31
|
+
def initialize(options)
|
|
32
|
+
super(options.reverse_merge(:case_sensitive => true))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def setup(klass)
|
|
36
|
+
@klass = klass
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def validate_each(record, attribute, value)
|
|
40
|
+
conditions = scope_conditions(record)
|
|
41
|
+
|
|
42
|
+
if options[:case_sensitive]
|
|
43
|
+
conditions[attribute] = value
|
|
44
|
+
else
|
|
45
|
+
conditions[attribute] = /^#{Regexp.escape(value.to_s)}$/i
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Make sure we're not including the current document in the query
|
|
49
|
+
conditions[:_id.ne] = record._id if record._id
|
|
50
|
+
|
|
51
|
+
if @klass.exists?(conditions)
|
|
52
|
+
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def message(instance)
|
|
57
|
+
super || "has already been taken"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def scope_conditions(instance)
|
|
61
|
+
Array(options[:scope] || []).inject({}) do |conditions, key|
|
|
62
|
+
conditions.merge(key => instance[key])
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class AssociatedValidator < ::ActiveModel::EachValidator
|
|
68
|
+
def validate_each(record, attribute, value)
|
|
69
|
+
if !Array.wrap(value).all? { |c| c.nil? || c.valid?(options[:context]) }
|
|
70
|
+
record.errors.add(attribute, :invalid, :message => options[:message], :value => value)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Need to monkey patch ActiveModel for now since it uses the internal
|
|
80
|
+
# _run_validation_callbacks, which is impossible to override due to the
|
|
81
|
+
# way ActiveSupport::Callbacks is implemented.
|
|
82
|
+
ActiveModel::Validations::Callbacks.class_eval do
|
|
83
|
+
def run_validations!
|
|
84
|
+
run_callbacks(:validation) { super }
|
|
85
|
+
end
|
|
86
|
+
end
|