chhean-mongoid 2.0.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/MIT_LICENSE +20 -0
  2. data/README.rdoc +49 -0
  3. data/lib/mongoid.rb +139 -0
  4. data/lib/mongoid/associations.rb +327 -0
  5. data/lib/mongoid/associations/embedded_in.rb +72 -0
  6. data/lib/mongoid/associations/embeds_many.rb +262 -0
  7. data/lib/mongoid/associations/embeds_one.rb +95 -0
  8. data/lib/mongoid/associations/foreign_key.rb +35 -0
  9. data/lib/mongoid/associations/meta_data.rb +29 -0
  10. data/lib/mongoid/associations/options.rb +73 -0
  11. data/lib/mongoid/associations/proxy.rb +33 -0
  12. data/lib/mongoid/associations/referenced_in.rb +71 -0
  13. data/lib/mongoid/associations/references_many.rb +243 -0
  14. data/lib/mongoid/associations/references_many_as_array.rb +78 -0
  15. data/lib/mongoid/associations/references_one.rb +116 -0
  16. data/lib/mongoid/attributes.rb +226 -0
  17. data/lib/mongoid/callbacks.rb +17 -0
  18. data/lib/mongoid/collection.rb +120 -0
  19. data/lib/mongoid/collections.rb +41 -0
  20. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  21. data/lib/mongoid/collections/master.rb +29 -0
  22. data/lib/mongoid/collections/operations.rb +41 -0
  23. data/lib/mongoid/collections/slaves.rb +45 -0
  24. data/lib/mongoid/components.rb +32 -0
  25. data/lib/mongoid/config.rb +237 -0
  26. data/lib/mongoid/contexts.rb +24 -0
  27. data/lib/mongoid/contexts/enumerable.rb +151 -0
  28. data/lib/mongoid/contexts/ids.rb +25 -0
  29. data/lib/mongoid/contexts/mongo.rb +285 -0
  30. data/lib/mongoid/contexts/paging.rb +50 -0
  31. data/lib/mongoid/criteria.rb +230 -0
  32. data/lib/mongoid/criterion/complex.rb +21 -0
  33. data/lib/mongoid/criterion/exclusion.rb +65 -0
  34. data/lib/mongoid/criterion/inclusion.rb +110 -0
  35. data/lib/mongoid/criterion/optional.rb +136 -0
  36. data/lib/mongoid/cursor.rb +82 -0
  37. data/lib/mongoid/deprecation.rb +22 -0
  38. data/lib/mongoid/dirty.rb +254 -0
  39. data/lib/mongoid/document.rb +264 -0
  40. data/lib/mongoid/errors.rb +124 -0
  41. data/lib/mongoid/extensions.rb +106 -0
  42. data/lib/mongoid/extensions/array/accessors.rb +17 -0
  43. data/lib/mongoid/extensions/array/aliasing.rb +4 -0
  44. data/lib/mongoid/extensions/array/assimilation.rb +26 -0
  45. data/lib/mongoid/extensions/array/conversions.rb +27 -0
  46. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  47. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  48. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  49. data/lib/mongoid/extensions/boolean/conversions.rb +22 -0
  50. data/lib/mongoid/extensions/date/conversions.rb +24 -0
  51. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  52. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  53. data/lib/mongoid/extensions/hash/accessors.rb +38 -0
  54. data/lib/mongoid/extensions/hash/assimilation.rb +39 -0
  55. data/lib/mongoid/extensions/hash/conversions.rb +45 -0
  56. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  57. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  58. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  59. data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
  60. data/lib/mongoid/extensions/object/conversions.rb +27 -0
  61. data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
  62. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  63. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  64. data/lib/mongoid/extensions/string/conversions.rb +15 -0
  65. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  66. data/lib/mongoid/extensions/symbol/inflections.rb +39 -0
  67. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  68. data/lib/mongoid/extras.rb +61 -0
  69. data/lib/mongoid/factory.rb +20 -0
  70. data/lib/mongoid/field.rb +80 -0
  71. data/lib/mongoid/fields.rb +61 -0
  72. data/lib/mongoid/finders.rb +144 -0
  73. data/lib/mongoid/identity.rb +39 -0
  74. data/lib/mongoid/indexes.rb +27 -0
  75. data/lib/mongoid/javascript.rb +21 -0
  76. data/lib/mongoid/javascript/functions.yml +37 -0
  77. data/lib/mongoid/matchers.rb +35 -0
  78. data/lib/mongoid/matchers/all.rb +11 -0
  79. data/lib/mongoid/matchers/default.rb +26 -0
  80. data/lib/mongoid/matchers/exists.rb +13 -0
  81. data/lib/mongoid/matchers/gt.rb +11 -0
  82. data/lib/mongoid/matchers/gte.rb +11 -0
  83. data/lib/mongoid/matchers/in.rb +11 -0
  84. data/lib/mongoid/matchers/lt.rb +11 -0
  85. data/lib/mongoid/matchers/lte.rb +11 -0
  86. data/lib/mongoid/matchers/ne.rb +11 -0
  87. data/lib/mongoid/matchers/nin.rb +11 -0
  88. data/lib/mongoid/matchers/size.rb +11 -0
  89. data/lib/mongoid/memoization.rb +33 -0
  90. data/lib/mongoid/named_scope.rb +37 -0
  91. data/lib/mongoid/observable.rb +30 -0
  92. data/lib/mongoid/paths.rb +62 -0
  93. data/lib/mongoid/persistence.rb +218 -0
  94. data/lib/mongoid/persistence/command.rb +39 -0
  95. data/lib/mongoid/persistence/insert.rb +47 -0
  96. data/lib/mongoid/persistence/insert_embedded.rb +38 -0
  97. data/lib/mongoid/persistence/remove.rb +39 -0
  98. data/lib/mongoid/persistence/remove_all.rb +37 -0
  99. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  100. data/lib/mongoid/persistence/update.rb +63 -0
  101. data/lib/mongoid/railtie.rb +54 -0
  102. data/lib/mongoid/railties/database.rake +37 -0
  103. data/lib/mongoid/scope.rb +75 -0
  104. data/lib/mongoid/state.rb +32 -0
  105. data/lib/mongoid/timestamps.rb +27 -0
  106. data/lib/mongoid/validations.rb +51 -0
  107. data/lib/mongoid/validations/associated.rb +32 -0
  108. data/lib/mongoid/validations/locale/en.yml +4 -0
  109. data/lib/mongoid/validations/uniqueness.rb +50 -0
  110. data/lib/mongoid/version.rb +4 -0
  111. data/lib/mongoid/versioning.rb +27 -0
  112. data/lib/rails/generators/mongoid/config/config_generator.rb +41 -0
  113. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
  114. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  115. data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
  116. data/lib/rails/generators/mongoid_generator.rb +61 -0
  117. metadata +284 -0
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Insert is a persistence command responsible for taking a document that
5
+ # has not been saved to the database and saving it.
6
+ #
7
+ # The underlying query resembles the following MongoDB query:
8
+ #
9
+ # collection.insert(
10
+ # { "_id" : 1, "field" : "value" },
11
+ # false
12
+ # );
13
+ class Insert < Command
14
+ # Insert the new document in the database. This delegates to the standard
15
+ # MongoDB collection's insert command.
16
+ #
17
+ # Example:
18
+ #
19
+ # <tt>Insert.persist</tt>
20
+ #
21
+ # Returns:
22
+ #
23
+ # The +Document+, whether the insert succeeded or not.
24
+ def persist
25
+ return @document if @validate && !@document.valid?
26
+ @document.run_callbacks(:create) do
27
+ @document.run_callbacks(:save) do
28
+ if insert
29
+ @document.new_record = false
30
+ @document.move_changes
31
+ end
32
+ end
33
+ end; @document
34
+ end
35
+
36
+ protected
37
+ # Insert the document into the database.
38
+ def insert
39
+ if @document.embedded?
40
+ Persistence::InsertEmbedded.new(@document, @validate).persist
41
+ else
42
+ @collection.insert(@document.raw_attributes, @options)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Insert is a persistence command responsible for taking a document that
5
+ # has not been saved to the database and saving it. This specific class
6
+ # handles the case when the document is embedded in another.
7
+ #
8
+ # The underlying query resembles the following MongoDB query:
9
+ #
10
+ # collection.insert(
11
+ # { "_id" : 1, "field" : "value" },
12
+ # false
13
+ # );
14
+ class InsertEmbedded < Command
15
+ # Insert the new document in the database. If the document's parent is a
16
+ # new record, we will call save on the parent, otherwise we will $push
17
+ # the document onto the parent.
18
+ #
19
+ # Example:
20
+ #
21
+ # <tt>Insert.persist</tt>
22
+ #
23
+ # Returns:
24
+ #
25
+ # The +Document+, whether the insert succeeded or not.
26
+ def persist
27
+ parent = @document._parent
28
+ if parent.new_record?
29
+ parent.insert
30
+ else
31
+ update = { @document._inserter => { @document._position => @document.raw_attributes } }
32
+ @collection.update(parent._selector, update, @options.merge(:multi => false))
33
+ end
34
+ @document.new_record = false; @document
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Remove is a persistence command responsible for deleting a document from
5
+ # the database.
6
+ #
7
+ # The underlying query resembles the following MongoDB query:
8
+ #
9
+ # collection.remove(
10
+ # { "_id" : 1 },
11
+ # false
12
+ # );
13
+ class Remove < Command
14
+ # Remove the document from the database: delegates to the MongoDB
15
+ # collection remove method.
16
+ #
17
+ # Example:
18
+ #
19
+ # <tt>Remove.persist</tt>
20
+ #
21
+ # Returns:
22
+ #
23
+ # +true+ if success, +false+ if not.
24
+ def persist
25
+ remove
26
+ end
27
+
28
+ protected
29
+ # Remove the document from the database.
30
+ def remove
31
+ if @document.embedded?
32
+ Persistence::RemoveEmbedded.new(@document, @validate).persist
33
+ else
34
+ @collection.remove({ :_id => @document.id }, @options)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Remove is a persistence command responsible for deleting a document from
5
+ # the database.
6
+ #
7
+ # The underlying query resembles the following MongoDB query:
8
+ #
9
+ # collection.remove(
10
+ # { "field" : value },
11
+ # false
12
+ # );
13
+ class RemoveAll < Command
14
+ # Remove the document from the database: delegates to the MongoDB
15
+ # collection remove method.
16
+ #
17
+ # Example:
18
+ #
19
+ # <tt>Remove.persist</tt>
20
+ #
21
+ # Returns:
22
+ #
23
+ # +true+ if success, +false+ if not.
24
+ def persist
25
+ remove
26
+ end
27
+
28
+ protected
29
+ # Remove the document from the database.
30
+ def remove
31
+ count = @collection.find(@selector.merge(:_type => @klass.name)).count
32
+ @collection.remove(@selector, @options)
33
+ count
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Remove is a persistence command responsible for deleting a document from
5
+ # the database.
6
+ #
7
+ # The underlying query resembles the following MongoDB query:
8
+ #
9
+ # collection.remove(
10
+ # { "_id" : 1 },
11
+ # false
12
+ # );
13
+ class RemoveEmbedded < Command
14
+ # Insert the new document in the database. If the document's parent is a
15
+ # new record, we will call save on the parent, otherwise we will $push
16
+ # the document onto the parent.
17
+ #
18
+ # Remove the document from the database. If the parent is a new record,
19
+ # it will get removed in Ruby only. If the parent is not a new record
20
+ # then either an $unset or $set will occur, depending if it's an
21
+ # embeds_one or embeds_many.
22
+ #
23
+ # Example:
24
+ #
25
+ # <tt>RemoveEmbedded.persist</tt>
26
+ #
27
+ # Returns:
28
+ #
29
+ # +true+ or +false+, depending on if the removal passed.
30
+ def persist
31
+ parent = @document._parent
32
+ parent.remove(@document)
33
+ unless parent.new_record?
34
+ update = { @document._remover => removal_selector }
35
+ @collection.update(parent._selector, update, @options.merge(:multi => false))
36
+ end; true
37
+ end
38
+
39
+ protected
40
+ # Get the value to pass to the removal modifier.
41
+ def setter
42
+ @document._index ? @document.id : true
43
+ end
44
+
45
+ def removal_selector
46
+ @document._index ? { @document._pull => { "_id" => @document.id } } : { @document._path => setter }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Update is a persistence command responsible for taking a document that
5
+ # has already been saved to the database and saving it, depending on
6
+ # whether or not the document has been modified.
7
+ #
8
+ # Before persisting the command will check via dirty attributes if the
9
+ # document has changed, if not, it will simply return true. If it has it
10
+ # will go through the validation steps, run callbacks, and set the changed
11
+ # fields atomically on the document. The underlying query resembles the
12
+ # following MongoDB query:
13
+ #
14
+ # collection.update(
15
+ # { "_id" : 1,
16
+ # { "$set" : { "field" : "value" },
17
+ # false,
18
+ # false
19
+ # );
20
+ #
21
+ # For embedded documents it will use the positional locator:
22
+ #
23
+ # collection.update(
24
+ # { "_id" : 1, "addresses._id" : 2 },
25
+ # { "$set" : { "addresses.$.field" : "value" },
26
+ # false,
27
+ # false
28
+ # );
29
+ #
30
+ class Update < Command
31
+ # Persist the document that is to be updated to the database. This will
32
+ # only write changed fields via MongoDB's $set modifier operation.
33
+ #
34
+ # Example:
35
+ #
36
+ # <tt>Update.persist</tt>
37
+ #
38
+ # Returns:
39
+ #
40
+ # +true+ or +false+, depending on validation.
41
+ def persist
42
+ return false if validate && !@document.valid?
43
+ @document.run_callbacks(:save) do
44
+ @document.run_callbacks(:update) do
45
+ if update
46
+ @document.move_changes
47
+ else
48
+ return false
49
+ end
50
+ end
51
+ end; true
52
+ end
53
+
54
+ protected
55
+ # Update the document in the database atomically.
56
+ def update
57
+ if @document.changed?
58
+ @collection.update(@document._selector, { "$set" => @document.setters }, @options.merge(:multi => false))
59
+ end; true
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,54 @@
1
+ require "rails"
2
+ module Rails #:nodoc:
3
+ module Mongoid #:nodoc:
4
+ class Railtie < Rails::Railtie #:nodoc:
5
+
6
+ # do we want a custom log subscriber for mongoid?
7
+ # log_subscriber :mongoid, ::Mongoid::Railties::LogSubscriber.new
8
+
9
+ rake_tasks do
10
+ load "mongoid/railties/database.rake"
11
+ end
12
+
13
+ # Initialize Mongoid. This will look for a mongoid.yml in the config
14
+ # directory and configure mongoid appropriately.
15
+ #
16
+ # Example mongoid.yml:
17
+ #
18
+ # defaults: &defaults
19
+ # host: localhost
20
+ # slaves:
21
+ # # - host: localhost
22
+ # # port: 27018
23
+ # # - host: localhost
24
+ # # port: 27019
25
+ # allow_dynamic_fields: false
26
+ # parameterize_keys: false
27
+ # persist_in_safe_mode: false
28
+ #
29
+ # development:
30
+ # <<: *defaults
31
+ # database: mongoid
32
+ initializer "setup database" do
33
+ config_file = Rails.root.join("config", "mongoid.yml")
34
+ if config_file.file?
35
+ settings = YAML.load(ERB.new(config_file.read).result)[Rails.env]
36
+ ::Mongoid.from_hash(settings) if settings.present?
37
+ end
38
+ end
39
+
40
+ initializer "verify that mongoid is configured" do
41
+ config.after_initialize do
42
+ begin
43
+ ::Mongoid.master
44
+ rescue ::Mongoid::Errors::InvalidDatabase => e
45
+ unless Rails.root.join("config", "mongoid.yml").file?
46
+ puts "\nMongoid config not found. Create a config file at: config/mongoid.yml"
47
+ puts "to generate one run: script/rails generate mongoid:config\n\n"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ namespace :db do
2
+
3
+ desc 'Drops all the collections for the database for the current Rails.env'
4
+ task :drop => :environment do
5
+ Mongoid.master.collections.each{|col| col.drop unless col.name == 'system.users' }
6
+ end
7
+
8
+ desc 'Load the seed data from db/seeds.rb'
9
+ task :seed => :environment do
10
+ seed_file = File.join(Rails.root, 'db', 'seeds.rb')
11
+ load(seed_file) if File.exist?(seed_file)
12
+ end
13
+
14
+ desc 'Create the database, and initialize with the seed data'
15
+ task :setup => [ 'db:create', 'db:seed' ]
16
+
17
+ desc 'Delete data and seed'
18
+ task :reseed => [ 'db:drop', 'db:seed' ]
19
+
20
+ task :create => :environment do
21
+ # noop
22
+ end
23
+
24
+ task :migrate => :environment do
25
+ # noop
26
+ end
27
+
28
+ namespace :schema do
29
+ task :load do
30
+ # noop
31
+ end
32
+ end
33
+
34
+ ########
35
+ # TODO: lots more useful db tasks can be added here. stuff like copyDatabase, etc
36
+ ########
37
+ end
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ class Scope #:nodoc:
4
+
5
+ delegate :scopes, :to => :parent
6
+
7
+ attr_reader :parent, :conditions
8
+
9
+ # If the other is a scope then compare the parent and conditions, otherwise
10
+ # if its enumerable collect and compare.
11
+ def ==(other)
12
+ case other
13
+ when Scope
14
+ @parent == other.parent && @conditions == other.conditions
15
+ when Enumerable
16
+ @collection ||= entries
17
+ return (@collection == other)
18
+ else
19
+ return false
20
+ end
21
+ end
22
+
23
+ # Create the new +Scope+. If a block is passed in, this Scope will extend
24
+ # the block.
25
+ #
26
+ # Options:
27
+ #
28
+ # parent: The class the scope belongs to, or a parent +Scope+.
29
+ # conditions: A +Hash+ of conditions.
30
+ #
31
+ # Example:
32
+ #
33
+ # Mongoid::Scope.new(Person, { :title => "Sir" }) do
34
+ # def knighted?
35
+ # title == "Sir"
36
+ # end
37
+ # end
38
+ def initialize(parent, conditions, &block)
39
+ @parent, @conditions = parent, conditions
40
+ extend Module.new(&block) if block_given?
41
+ end
42
+
43
+ # Return the class for the +Scope+. This will be the parent if the parent
44
+ # is a class, otherwise will be nil.
45
+ def klass
46
+ @klass ||= @parent unless @parent.is_a?(Scope)
47
+ end
48
+
49
+ # Chaining is supported through method_missing. If a scope is already
50
+ # defined with the method name the call will be passed there, otherwise it
51
+ # will be passed to the target or parent.
52
+ def method_missing(name, *args, &block)
53
+ if scopes.include?(name)
54
+ scopes[name].call(self, *args)
55
+ elsif klass
56
+ target.send(name, *args, &block)
57
+ else
58
+ @parent.fuse(@conditions); @parent.send(name, *args, &block)
59
+ end
60
+ end
61
+
62
+ # The +Scope+ must respond like a +Criteria+ object. If this is a parent
63
+ # criteria delegate to the target, otherwise bubble up to the parent.
64
+ def respond_to?(name)
65
+ super || (klass ? target.respond_to?(name) : @parent.respond_to?(name))
66
+ end
67
+
68
+ # Returns the target criteria if it has already been set or creates a new
69
+ # criteria from the parent class.
70
+ def target
71
+ @target ||= klass.criteria.fuse(@conditions)
72
+ end
73
+ end
74
+ end
75
+