mongoid 2.0.0.beta.12 → 2.0.0.beta.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,7 +11,7 @@ Mongoid is an ODM (Object-Document-Mapper) framework for MongoDB in Ruby.
11
11
 
12
12
  == Compatibility
13
13
 
14
- Mongoid is developed against Ruby 1.8.7, 1.9.1, 1.9.2
14
+ Mongoid is developed against Ruby 1.8.7, 1.9.1, 1.9.2, and REE.
15
15
 
16
16
  = Documentation
17
17
 
@@ -149,19 +149,18 @@ module Mongoid #:nodoc:
149
149
  extends(options)
150
150
  end
151
151
 
152
-
153
-
154
152
  # If the target array does not respond to the supplied method then try to
155
153
  # find a named scope or criteria on the class and send the call there.
156
154
  #
157
155
  # If the method exists on the array, use the default proxy behavior.
158
156
  def method_missing(name, *args, &block)
159
- unless @target.respond_to?(name)
160
- object = @klass.send(name, *args)
161
- object.documents = @target
162
- return object
157
+ if @target.respond_to?(name)
158
+ super
159
+ else
160
+ @klass.send(:with_scope, criteria) do
161
+ object = @klass.send(name, *args)
162
+ end
163
163
  end
164
- super
165
164
  end
166
165
 
167
166
  # Used for setting associations via a nested attributes setter from the
@@ -242,6 +241,14 @@ module Mongoid #:nodoc:
242
241
  end; count
243
242
  end
244
243
 
244
+ # Returns the criteria object for the target class with its documents set
245
+ # to @target.
246
+ def criteria
247
+ criteria = @klass.criteria
248
+ criteria.documents = @target
249
+ criteria
250
+ end
251
+
245
252
  class << self
246
253
 
247
254
  # Preferred method of creating a new +EmbedsMany+ association. It will
@@ -32,6 +32,7 @@ module Mongoid #:nodoc:
32
32
  end
33
33
  end
34
34
  @target << object
35
+ object.save unless @parent.new_record?
35
36
  end
36
37
  end
37
38
 
@@ -166,7 +166,7 @@ module Mongoid #:nodoc
166
166
  _master(settings)
167
167
  _slaves(settings)
168
168
  settings.except("database", "slaves").each_pair do |name, value|
169
- send("#{name}=", value) if respond_to?(name)
169
+ send("#{name}=", value) if respond_to?("#{name}=")
170
170
  end
171
171
  end
172
172
 
@@ -63,12 +63,6 @@ module Mongoid #:nodoc:
63
63
  end
64
64
  end
65
65
 
66
- # Returns true if the supplied +Object+ is an instance of +Criteria+ or
67
- # +Scope+.
68
- def self.===(other)
69
- super || Scope === other
70
- end
71
-
72
66
  # Return or create the context in which this criteria should be executed.
73
67
  #
74
68
  # This will return an Enumerable context if the class is embedded,
@@ -153,9 +147,9 @@ module Mongoid #:nodoc:
153
147
  # Returns: <tt>Criteria</tt>
154
148
  def method_missing(name, *args)
155
149
  if @klass.respond_to?(name)
156
- new_scope = @klass.send(name, *args)
157
- new_scope.merge(self) if Criteria === new_scope
158
- return new_scope
150
+ @klass.send(:with_scope, self) do
151
+ @klass.send(name, *args)
152
+ end
159
153
  else
160
154
  return entries.send(name, *args)
161
155
  end
@@ -13,6 +13,17 @@ module Mongoid #:nodoc:
13
13
  end
14
14
  end
15
15
 
16
+ class << self
17
+
18
+ # Returns all classes that have included Mongoid::Document.
19
+ #
20
+ # This will not get subclasses of the top level models, for those we will
21
+ # use Class.descendents in the rake task for indexes.
22
+ def descendants
23
+ (@@descendants ||= {}).keys
24
+ end
25
+ end
26
+
16
27
  module ClassMethods #:nodoc:
17
28
 
18
29
  # Perform default behavior but mark the hierarchy as being hereditary.
@@ -42,17 +53,12 @@ module Mongoid #:nodoc:
42
53
  end
43
54
  end
44
55
 
45
- # Returns the classes that have included Mongoid::Document
46
- def self.descendents
47
- (@@descendants ||= {}).keys
48
- end
49
-
50
56
  # Returns all types to query for when using this class as the base.
51
57
  # *subclasses* is from activesupport. Note that a bug in *subclasses*
52
58
  # causes the first call to only return direct children, hence
53
59
  # the double call and unique.
54
60
  def _types
55
- @_type ||= [subclasses + subclasses + [self.name]].flatten.uniq.map(&:to_s)
61
+ @_type ||= [descendants + [self]].flatten.uniq.map(&:to_s)
56
62
  end
57
63
  end
58
64
 
@@ -39,13 +39,14 @@ module Mongoid #:nodoc:
39
39
  Criteria.translate(self, *args).limit(1).count == 1
40
40
  end
41
41
 
42
- # Helper to initialize a new +Criteria+ object for this class.
42
+ # Helper to initialize a new +Criteria+ object for this class, or return
43
+ # the currently scoped +Criteria+ object.
43
44
  #
44
45
  # Example:
45
46
  #
46
47
  # <tt>Person.criteria</tt>
47
48
  def criteria
48
- Criteria.new(self)
49
+ scope_stack.last || Criteria.new(self)
49
50
  end
50
51
 
51
52
  # Find a +Document+ in several different ways.
@@ -141,5 +142,24 @@ module Mongoid #:nodoc:
141
142
  def find_or(method, attrs = {})
142
143
  first(:conditions => attrs) || send(method, attrs)
143
144
  end
145
+
146
+ # Initializes and returns the current scope stack.
147
+ def scope_stack
148
+ scope_stack_for = Thread.current[:mongoid_scope_stack] ||= {}
149
+ scope_stack_for[object_id] ||= []
150
+ end
151
+
152
+ # Pushes the provided criteria onto the scope stack, and removes it after the
153
+ # provided block is yielded.
154
+ def with_scope(criteria)
155
+ scope_stack = self.scope_stack
156
+ scope_stack << criteria
157
+
158
+ begin
159
+ yield criteria
160
+ ensure
161
+ scope_stack.pop
162
+ end
163
+ end
144
164
  end
145
165
  end
@@ -12,9 +12,9 @@ module Mongoid #:nodoc
12
12
  # Send the actual index creation comments to the MongoDB driver
13
13
  def create_indexes
14
14
  return unless index_options
15
-
15
+ current_collection = self._collection || set_collection
16
16
  index_options.each do |name, options|
17
- self._collection.create_index(name, options)
17
+ current_collection.create_index(name, options)
18
18
  end
19
19
  end
20
20
 
@@ -14,6 +14,5 @@ module Mongoid
14
14
  def inspect
15
15
  "#<Mongoid::Logger:0x#{object_id.to_s(16)} @logger=#{logger.inspect}>"
16
16
  end
17
-
18
17
  end
19
18
  end
@@ -16,14 +16,13 @@ module Mongoid #:nodoc:
16
16
  # named_scope :count_gt_one, :where => { :count.gt => 1 }
17
17
  # named_scope :at_least_count, lambda { |count| { :where => { :count.gt => count } } }
18
18
  # end
19
- def named_scope(name, options = {}, &block)
19
+ def named_scope(name, conditions = {}, &block)
20
20
  name = name.to_sym
21
- scopes[name] = lambda do |parent, *args|
22
- Scope.new(parent, options.scoped(*args), &block)
23
- end
21
+ scopes[name] = Scope.new(conditions, &block)
24
22
  (class << self; self; end).class_eval <<-EOT
25
23
  def #{name}(*args)
26
- scopes[:#{name}].call(self, *args)
24
+ scope = scopes[:#{name}]
25
+ scope.extend(criteria.fuse(scope.conditions.scoped(*args)))
27
26
  end
28
27
  EOT
29
28
  end
@@ -1,6 +1,9 @@
1
+ # encoding: utf-8
1
2
  require "singleton"
2
- require "rails"
3
3
  require "mongoid/config"
4
+ require "rails"
5
+ require "rails/mongoid"
6
+
4
7
  module Rails #:nodoc:
5
8
  module Mongoid #:nodoc:
6
9
  class Railtie < Rails::Railtie #:nodoc:
@@ -50,6 +53,9 @@ module Rails #:nodoc:
50
53
  end
51
54
  end
52
55
 
56
+ # After initialization we will attempt to connect to the database, if
57
+ # we get an exception and can't find a mongoid.yml we will alert the user
58
+ # to generate one.
53
59
  initializer "verify that mongoid is configured" do
54
60
  config.after_initialize do
55
61
  begin
@@ -63,8 +69,20 @@ module Rails #:nodoc:
63
69
  end
64
70
  end
65
71
 
72
+ # Due to all models not getting loaded and messing up inheritance queries
73
+ # and indexing, we need to preload the models in order to address this.
74
+ #
75
+ # This will happen every request in development, once in ther other
76
+ # environments.
77
+ initializer "preload all application models" do |app|
78
+ config.to_prepare do
79
+ ::Rails::Mongoid.load_models(app)
80
+ end
81
+ end
82
+
66
83
  initializer "reconnect to master if application is preloaded" do
67
84
  config.after_initialize do
85
+
68
86
  # Unicorn clears the START_CTX when a worker is forked, so if we have
69
87
  # data in START_CTX then we know we're being preloaded. Unicorn does
70
88
  # not provide application-level hooks for executing code after the
@@ -57,9 +57,7 @@ namespace :db do
57
57
  if not Rake::Task.task_defined?("db:create_indexes")
58
58
  desc 'Create the indexes defined on your mongoid models'
59
59
  task :create_indexes => :environment do
60
- Mongoid::Document.descendents.each do |model|
61
- model.create_indexes
62
- end
60
+ ::Rails::Mongoid.index_children(Mongoid::Document.descendants)
63
61
  end
64
62
  end
65
63
 
@@ -2,74 +2,25 @@
2
2
  module Mongoid #:nodoc:
3
3
  class Scope #:nodoc:
4
4
 
5
- delegate :scopes, :to => :parent
5
+ attr_reader :conditions, :extensions
6
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.
7
+ # Create the new +Scope+. If a block is passed in, this Scope will store
8
+ # the block for future calls to #extend.
25
9
  #
26
10
  # Options:
27
11
  #
28
- # parent: The class the scope belongs to, or a parent +Scope+.
29
12
  # conditions: A +Hash+ of conditions.
13
+ # block: A +block+ of extension methods (optional)
30
14
  #
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?
15
+ def initialize(conditions = {}, &block)
16
+ @conditions = conditions
17
+ @extensions = Module.new(&block) if block_given?
41
18
  end
42
19
 
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)
20
+ def extend(criteria)
21
+ @extensions ? criteria.extend(@extensions) : criteria
47
22
  end
48
23
 
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
24
  end
74
25
  end
75
26
 
@@ -21,16 +21,12 @@ module Mongoid #:nodoc:
21
21
  def validate_each(document, attribute, value)
22
22
  if document.embedded?
23
23
  return if document._parent.nil?
24
-
25
24
  criteria = document._parent.send(document.association_name)
26
-
27
25
  # If the parent document embeds_one, no need to validate uniqueness
28
26
  return if criteria.is_a?(Mongoid::Document)
29
-
30
27
  criteria = criteria.where(attribute => value, :_id => {'$ne' => document._id})
31
28
  else
32
29
  criteria = @klass.where(attribute => value)
33
-
34
30
  unless document.new_record?
35
31
  criteria = criteria.where(:_id => {'$ne' => document._id})
36
32
  end
@@ -39,9 +35,12 @@ module Mongoid #:nodoc:
39
35
  Array.wrap(options[:scope]).each do |item|
40
36
  criteria = criteria.where(item => document.attributes[item])
41
37
  end
42
-
43
38
  if criteria.exists?
44
- document.errors.add(attribute, :taken, :default => options[:message], :value => value)
39
+ document.errors.add(
40
+ attribute,
41
+ :taken,
42
+ options.except(:case_sensistive, :scope).merge(:value => value)
43
+ )
45
44
  end
46
45
  end
47
46
 
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
- VERSION = "2.0.0.beta.12"
3
+ VERSION = "2.0.0.beta.13"
4
4
  end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ module Rails #:nodoc:
3
+ module Mongoid #:nodoc:
4
+ class << self
5
+
6
+ # Use the application configuration to get every model and require it, so
7
+ # that indexing and inheritance work in both development and production
8
+ # with the same results.
9
+ def load_models(app)
10
+ app.config.paths.app.models.each do |path|
11
+ Dir.glob("#{path}/**/*.rb").sort.each do |file|
12
+ require_dependency(file)
13
+ end
14
+ end
15
+ end
16
+
17
+ # Recursive function to create all the indexes for the model, then
18
+ # potentially and subclass of the model since both are still root
19
+ # documents in the hierarchy.
20
+ #
21
+ # Note there is a tricky naming scheme going on here that needs to be
22
+ # revisisted. Module.descendants vs Class.descendents is way too
23
+ # confusing.
24
+ def index_children(children)
25
+ children.each do |model|
26
+ Logger.new($stdout).info("Generating indexes for #{model}")
27
+ model.create_indexes
28
+ index_children(model.descendants)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196475
4
+ hash: 62196473
5
5
  prerelease: true
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
9
  - 0
10
10
  - beta
11
- - 12
12
- version: 2.0.0.beta.12
11
+ - 13
12
+ version: 2.0.0.beta.13
13
13
  platform: ruby
14
14
  authors:
15
15
  - Durran Jordan
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-07-26 00:00:00 -04:00
20
+ date: 2010-07-27 00:00:00 -04:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
@@ -26,15 +26,15 @@ dependencies:
26
26
  requirement: &id001 !ruby/object:Gem::Requirement
27
27
  none: false
28
28
  requirements:
29
- - - ~>
29
+ - - "="
30
30
  - !ruby/object:Gem::Version
31
- hash: 31098225
31
+ hash: 7712042
32
32
  segments:
33
33
  - 3
34
34
  - 0
35
35
  - 0
36
- - beta
37
- version: 3.0.0.beta
36
+ - rc
37
+ version: 3.0.0.rc
38
38
  type: :runtime
39
39
  version_requirements: *id001
40
40
  - !ruby/object:Gem::Dependency
@@ -43,7 +43,7 @@ dependencies:
43
43
  requirement: &id002 !ruby/object:Gem::Requirement
44
44
  none: false
45
45
  requirements:
46
- - - ~>
46
+ - - "="
47
47
  - !ruby/object:Gem::Version
48
48
  hash: 63
49
49
  segments:
@@ -75,14 +75,14 @@ dependencies:
75
75
  requirement: &id004 !ruby/object:Gem::Requirement
76
76
  none: false
77
77
  requirements:
78
- - - ~>
78
+ - - "="
79
79
  - !ruby/object:Gem::Version
80
- hash: 29
80
+ hash: 27
81
81
  segments:
82
82
  - 1
83
83
  - 0
84
- - 5
85
- version: 1.0.5
84
+ - 6
85
+ version: 1.0.6
86
86
  type: :runtime
87
87
  version_requirements: *id004
88
88
  - !ruby/object:Gem::Dependency
@@ -91,7 +91,7 @@ dependencies:
91
91
  requirement: &id005 !ruby/object:Gem::Requirement
92
92
  none: false
93
93
  requirements:
94
- - - ~>
94
+ - - "="
95
95
  - !ruby/object:Gem::Version
96
96
  hash: 31
97
97
  segments:
@@ -107,7 +107,7 @@ dependencies:
107
107
  requirement: &id006 !ruby/object:Gem::Requirement
108
108
  none: false
109
109
  requirements:
110
- - - ~>
110
+ - - "="
111
111
  - !ruby/object:Gem::Version
112
112
  hash: 31
113
113
  segments:
@@ -141,14 +141,14 @@ dependencies:
141
141
  requirements:
142
142
  - - "="
143
143
  - !ruby/object:Gem::Version
144
- hash: 62196419
144
+ hash: 62196421
145
145
  segments:
146
146
  - 2
147
147
  - 0
148
148
  - 0
149
149
  - beta
150
- - 16
151
- version: 2.0.0.beta.16
150
+ - 19
151
+ version: 2.0.0.beta.19
152
152
  type: :development
153
153
  version_requirements: *id008
154
154
  - !ruby/object:Gem::Dependency
@@ -297,6 +297,7 @@ files:
297
297
  - lib/rails/generators/mongoid/model/model_generator.rb
298
298
  - lib/rails/generators/mongoid/model/templates/model.rb
299
299
  - lib/rails/generators/mongoid_generator.rb
300
+ - lib/rails/mongoid.rb
300
301
  - MIT_LICENSE
301
302
  - README.rdoc
302
303
  has_rdoc: true