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,144 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Finders #:nodoc:
4
+
5
+ # Delegate to the criteria methods that are natural for creating a new
6
+ # criteria.
7
+ [ :all_in, :any_in, :avg, :excludes, :limit, :max, :min,
8
+ :not_in, :only, :order_by, :skip, :sum, :where ].each do |name|
9
+ define_method(name) do |*args|
10
+ criteria.send(name, *args)
11
+ end
12
+ end
13
+
14
+ # Find +Documents+ given the conditions.
15
+ #
16
+ # Options:
17
+ #
18
+ # args: A +Hash+ with a conditions key and other options
19
+ #
20
+ # <tt>Person.all(:conditions => { :attribute => "value" })</tt>
21
+ def all(*args)
22
+ find(:all, *args)
23
+ end
24
+
25
+ # Returns a count of matching records in the database based on the
26
+ # provided arguments.
27
+ #
28
+ # <tt>Person.count(:first, :conditions => { :attribute => "value" })</tt>
29
+ def count(*args)
30
+ Criteria.translate(self, *args).count
31
+ end
32
+
33
+ # Returns true if there are on document in database based on the
34
+ # provided arguments.
35
+ #
36
+ # <tt>Person.exists?(:first, :conditions => { :attribute => "value" })</tt>
37
+ def exists?(*args)
38
+ Criteria.translate(self, *args).limit(1).count == 1
39
+ end
40
+
41
+ # Helper to initialize a new +Criteria+ object for this class.
42
+ #
43
+ # Example:
44
+ #
45
+ # <tt>Person.criteria</tt>
46
+ def criteria
47
+ Criteria.new(self)
48
+ end
49
+
50
+ # Find a +Document+ in several different ways.
51
+ #
52
+ # If a +String+ is provided, it will be assumed that it is a
53
+ # representation of a Mongo::ObjectID and will attempt to find a single
54
+ # +Document+ based on that id. If a +Symbol+ and +Hash+ is provided then
55
+ # it will attempt to find either a single +Document+ or multiples based
56
+ # on the conditions provided and the first parameter.
57
+ #
58
+ # <tt>Person.find(:first, :conditions => { :attribute => "value" })</tt>
59
+ #
60
+ # <tt>Person.find(:all, :conditions => { :attribute => "value" })</tt>
61
+ #
62
+ # <tt>Person.find(Mongo::ObjectID.new.to_s)</tt>
63
+ def find(*args)
64
+ raise Errors::InvalidOptions.new("Calling Document#find with nil is invalid") if args[0].nil?
65
+ type = args.delete_at(0) if args[0].is_a?(Symbol)
66
+ criteria = Criteria.translate(self, *args)
67
+ case type
68
+ when :first then return criteria.one
69
+ when :last then return criteria.last
70
+ else
71
+ return criteria
72
+ end
73
+ end
74
+
75
+ # Find the first +Document+ given the conditions, or creates a new document
76
+ # with the conditions that were supplied
77
+ #
78
+ # Options:
79
+ #
80
+ # args: A +Hash+ of attributes
81
+ #
82
+ # <tt>Person.find_or_create_by(:attribute => "value")</tt>
83
+ def find_or_create_by(attrs = {})
84
+ find_or(:create, attrs)
85
+ end
86
+
87
+ # Find the first +Document+ given the conditions, or instantiates a new document
88
+ # with the conditions that were supplied
89
+ #
90
+ # Options:
91
+ #
92
+ # args: A +Hash+ of attributes
93
+ #
94
+ # <tt>Person.find_or_initialize_by(:attribute => "value")</tt>
95
+ def find_or_initialize_by(attrs = {})
96
+ find_or(:new, attrs)
97
+ end
98
+
99
+ # Find the first +Document+ given the conditions.
100
+ #
101
+ # Options:
102
+ #
103
+ # args: A +Hash+ with a conditions key and other options
104
+ #
105
+ # <tt>Person.first(:conditions => { :attribute => "value" })</tt>
106
+ def first(*args)
107
+ find(:first, *args)
108
+ end
109
+
110
+ # Find the last +Document+ given the conditions.
111
+ #
112
+ # Options:
113
+ #
114
+ # args: A +Hash+ with a conditions key and other options
115
+ #
116
+ # <tt>Person.last(:conditions => { :attribute => "value" })</tt>
117
+ def last(*args)
118
+ find(:last, *args)
119
+ end
120
+
121
+ # Find all documents in paginated fashion given the supplied arguments.
122
+ # If no parameters are passed just default to offset 0 and limit 20.
123
+ #
124
+ # Options:
125
+ #
126
+ # params: A +Hash+ of params to pass to the Criteria API.
127
+ #
128
+ # Example:
129
+ #
130
+ # <tt>Person.paginate(:conditions => { :field => "Test" }, :page => 1,
131
+ # :per_page => 20)</tt>
132
+ #
133
+ # Returns paginated array of docs.
134
+ def paginate(params = {})
135
+ Criteria.translate(self, params).paginate
136
+ end
137
+
138
+ protected
139
+ # Find the first object or create/initialize it.
140
+ def find_or(method, attrs = {})
141
+ first(:conditions => attrs) || send(method, attrs)
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ class Identity #:nodoc:
4
+ class << self
5
+ # Create the identity for the +Document+.
6
+ #
7
+ # The id will be set in either in the form of a Mongo
8
+ # +ObjectID+ or a composite key set up by defining a key on the document.
9
+ #
10
+ # The _type will be set to the document's class name.
11
+ def create(doc)
12
+ identify(doc); type(doc); doc
13
+ end
14
+
15
+ protected
16
+ # Return the proper id for the document.
17
+ def generate_id
18
+ id = BSON::ObjectID.new
19
+ Mongoid.use_object_ids ? id : id.to_s
20
+ end
21
+
22
+ # Set the id for the document.
23
+ def identify(doc)
24
+ doc.id = compose(doc).join(" ").identify if doc.primary_key
25
+ doc.id = generate_id if doc.id.blank?
26
+ end
27
+
28
+ # Set the _type field on the document.
29
+ def type(doc)
30
+ doc._type = doc.class.name if doc.hereditary?
31
+ end
32
+
33
+ # Generates the composite key for a document.
34
+ def compose(doc)
35
+ doc.primary_key.collect { |key| doc.attributes[key] }.reject { |val| val.nil? }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ module Indexes #:nodoc
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ cattr_accessor :indexed
7
+ self.indexed = false
8
+ end
9
+
10
+ module ClassMethods #:nodoc
11
+ # Add the default indexes to the root document if they do not already
12
+ # exist. Currently this is only _type.
13
+ def add_indexes
14
+ if hereditary && !indexed
15
+ self._collection.create_index(:_type, :unique => false, :background => true)
16
+ self.indexed = true
17
+ end
18
+ end
19
+
20
+ # Adds an index on the field specified. Options can be :unique => true or
21
+ # :unique => false. It will default to the latter.
22
+ def index(name, options = { :unique => false })
23
+ collection.create_index(name, options)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ class Javascript
4
+ # Constant for the file that defines all the js functions.
5
+ FUNCTIONS = File.join(File.dirname(__FILE__), "javascript", "functions.yml")
6
+
7
+ # Load the javascript functions and define a class method for each one,
8
+ # that memoizes the value.
9
+ #
10
+ # Example:
11
+ #
12
+ # <tt>Mongoid::Javascript.aggregate</tt>
13
+ YAML.load(File.read(FUNCTIONS)).each_pair do |key, function|
14
+ (class << self; self; end).class_eval <<-EOT
15
+ def #{key}
16
+ @#{key} ||= "#{function}"
17
+ end
18
+ EOT
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ aggregate:
2
+ "function(obj, prev) {
3
+ prev.count++;
4
+ }"
5
+
6
+ group:
7
+ "function(obj, prev) {
8
+ prev.group.push(obj);
9
+ }"
10
+
11
+ max:
12
+ "function(obj, prev) {
13
+ if (prev.max == 'start') {
14
+ prev.max = obj.[field];
15
+ }
16
+ if (prev.max < obj.[field]) {
17
+ prev.max = obj.[field];
18
+ }
19
+ }"
20
+
21
+ min:
22
+ "function(obj, prev) {
23
+ if (prev.min == 'start') {
24
+ prev.min = obj.[field];
25
+ }
26
+ if (prev.min > obj.[field]) {
27
+ prev.min = obj.[field];
28
+ }
29
+ }"
30
+
31
+ sum:
32
+ "function(obj, prev) {
33
+ if (prev.sum == 'start') {
34
+ prev.sum = 0;
35
+ }
36
+ prev.sum += obj.[field];
37
+ }"
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ require "mongoid/matchers/default"
3
+ require "mongoid/matchers/all"
4
+ require "mongoid/matchers/exists"
5
+ require "mongoid/matchers/gt"
6
+ require "mongoid/matchers/gte"
7
+ require "mongoid/matchers/in"
8
+ require "mongoid/matchers/lt"
9
+ require "mongoid/matchers/lte"
10
+ require "mongoid/matchers/ne"
11
+ require "mongoid/matchers/nin"
12
+ require "mongoid/matchers/size"
13
+
14
+ module Mongoid #:nodoc:
15
+ module Matchers
16
+ # Determines if this document has the attributes to match the supplied
17
+ # MongoDB selector. Used for matching on embedded associations.
18
+ def matches?(selector)
19
+ selector.each_pair do |key, value|
20
+ return false unless matcher(key, value).matches?(value)
21
+ end; true
22
+ end
23
+
24
+ protected
25
+ # Get the matcher for the supplied key and value. Will determine the class
26
+ # name from the key.
27
+ def matcher(key, value)
28
+ if value.is_a?(Hash)
29
+ name = "Mongoid::Matchers::#{value.keys.first.gsub("$", "").camelize}"
30
+ return name.constantize.new(attributes[key])
31
+ end
32
+ Default.new(attributes[key])
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class All < Default
5
+ # Return true if the attribute and first value in the hash are equal.
6
+ def matches?(value)
7
+ @attribute == value.values.first
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class Default
5
+ # Creating a new matcher only requires the value.
6
+ def initialize(attribute)
7
+ @attribute = attribute
8
+ end
9
+ # Return true if the attribute and value are equal.
10
+ def matches?(value)
11
+ @attribute == value
12
+ end
13
+
14
+ protected
15
+ # Return the first value in the hash.
16
+ def first(value)
17
+ value.values.first
18
+ end
19
+
20
+ # If object exists then compare, else return false
21
+ def determine(value, operator)
22
+ @attribute ? @attribute.send(operator, first(value)) : false
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class Exists < Default
5
+ # Return true if the attribute exists and checking for existence or
6
+ # return true if the attribute does not exist and checking for
7
+ # non-existence.
8
+ def matches?(value)
9
+ @attribute.nil? != value.values.first
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class Gt < Default
5
+ # Return true if the attribute is greater than the value.
6
+ def matches?(value)
7
+ determine(value, :>)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class Gte < Default
5
+ # Return true if the attribute is greater than or equal to the value.
6
+ def matches?(value)
7
+ determine(value, :>=)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class In < Default
5
+ # Return true if the attribute is in the values.
6
+ def matches?(value)
7
+ value.values.first.include?(@attribute)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class Lt < Default
5
+ # Return true if the attribute is less than the value.
6
+ def matches?(value)
7
+ determine(value, :<)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class Lte < Default
5
+ # Return true if the attribute is less than or equal to the value.
6
+ def matches?(value)
7
+ determine(value, :<=)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Matchers #:nodoc:
4
+ class Ne < Default
5
+ # Return true if the attribute and first value are not equal.
6
+ def matches?(value)
7
+ @attribute != value.values.first
8
+ end
9
+ end
10
+ end
11
+ end