mongo_mapper 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/mongo_mapper.rb CHANGED
@@ -65,22 +65,6 @@ module MongoMapper
65
65
  autoload :OneEmbeddedProxy, 'mongo_mapper/plugins/associations/one_embedded_proxy'
66
66
  autoload :InArrayProxy, 'mongo_mapper/plugins/associations/in_array_proxy'
67
67
  end
68
-
69
- module DynamicQuerying
70
- autoload :DynamicFinder, 'mongo_mapper/plugins/dynamic_querying/dynamic_finder'
71
- end
72
-
73
- module Keys
74
- autoload :Key, 'mongo_mapper/plugins/keys/key'
75
- end
76
-
77
- module Querying
78
- autoload :Decorator, 'mongo_mapper/plugins/querying/decorator'
79
- end
80
- end
81
-
82
- module Support
83
- autoload :DescendantAppends, 'mongo_mapper/support/descendant_appends'
84
68
  end
85
69
 
86
70
  extend Connection
@@ -90,5 +74,7 @@ Dir[File.join(File.dirname(__FILE__), 'mongo_mapper', 'extensions', '*.rb')].eac
90
74
  require extension
91
75
  end
92
76
 
77
+ require 'mongo_mapper/support/descendant_appends'
78
+
93
79
  # FIXME: autoload with proxy is failing, need to investigate
94
80
  require 'mongo_mapper/plugins/associations/proxy'
@@ -3,7 +3,7 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Associations
5
5
  class InArrayProxy < Collection
6
- include MongoMapper::Plugins::DynamicQuerying::ClassMethods
6
+ include DynamicQuerying::ClassMethods
7
7
 
8
8
  def find(*args)
9
9
  query.find(*scoped_ids(args))
@@ -3,35 +3,8 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Associations
5
5
  class ManyDocumentsProxy < Collection
6
- include MongoMapper::Plugins::DynamicQuerying::ClassMethods
7
-
8
- def find(*args)
9
- query.find(*args)
10
- end
11
-
12
- def find!(*args)
13
- query.find!(*args)
14
- end
15
-
16
- def paginate(options)
17
- query.paginate(options)
18
- end
19
-
20
- def all(options={})
21
- query(options).all
22
- end
23
-
24
- def first(options={})
25
- query(options).first
26
- end
27
-
28
- def last(options={})
29
- query(options).last
30
- end
31
-
32
- def count(options={})
33
- query(options).count
34
- end
6
+ include DynamicQuerying::ClassMethods
7
+ include Querying::PluckyMethods
35
8
 
36
9
  def replace(docs)
37
10
  load_target
@@ -93,8 +66,17 @@ module MongoMapper
93
66
  def query(options={})
94
67
  klass.
95
68
  query(association.query_options).
96
- update(options).
97
- update(criteria)
69
+ update(options).update(criteria)
70
+ end
71
+
72
+ def method_missing(method, *args, &block)
73
+ if klass.respond_to?(method)
74
+ result = klass.send(method, *args, &block)
75
+ result.is_a?(Plucky::Query) ?
76
+ query.merge(result) : super
77
+ else
78
+ super
79
+ end
98
80
  end
99
81
 
100
82
  def criteria
@@ -18,7 +18,7 @@ module MongoMapper
18
18
  end
19
19
 
20
20
  def reload
21
- if doc = self.class.query.find_one(:_id => id)
21
+ if doc = collection.find_one(:_id => id)
22
22
  tap do |instance|
23
23
  instance.class.associations.each_key do |association_name|
24
24
  send(association_name).reset if respond_to?(association_name)
@@ -1,4 +1,6 @@
1
1
  # encoding: UTF-8
2
+ require 'mongo_mapper/plugins/dynamic_querying/dynamic_finder'
3
+
2
4
  module MongoMapper
3
5
  module Plugins
4
6
  module DynamicQuerying
@@ -30,21 +30,34 @@ module MongoMapper
30
30
  @identity_map = v
31
31
  end
32
32
 
33
- def find_one(options={})
34
- query = query(options)
35
-
36
- if query.simple? && identity_map.key?(query[:_id])
37
- identity_map[query[:_id]]
38
- else
39
- super.tap do |document|
40
- remove_documents_from_map(document) if query.fields?
33
+ module IdentityMapQueryMethods
34
+ def all(opts={})
35
+ query = clone.update(opts)
36
+ super.tap do |docs|
37
+ model.remove_documents_from_map(docs) if query.fields?
38
+ end
39
+ end
40
+
41
+ def find_one(opts={})
42
+ query = clone.update(opts)
43
+
44
+ if query.simple? && model.identity_map[query[:_id]]
45
+ model.identity_map[query[:_id]]
46
+ else
47
+ super.tap do |doc|
48
+ model.remove_documents_from_map(doc) if query.fields?
49
+ end
41
50
  end
42
51
  end
43
52
  end
44
53
 
45
- def find_many(options)
46
- super.tap do |documents|
47
- remove_documents_from_map(documents) if query(options).fields?
54
+ def query(opts={})
55
+ super.extend(IdentityMapQueryMethods)
56
+ end
57
+
58
+ def remove_documents_from_map(*documents)
59
+ documents.flatten.compact.each do |document|
60
+ identity_map.delete(document['_id'])
48
61
  end
49
62
  end
50
63
 
@@ -88,12 +101,6 @@ module MongoMapper
88
101
  end
89
102
 
90
103
  private
91
- def remove_documents_from_map(*documents)
92
- documents.flatten.compact.each do |document|
93
- identity_map.delete(document._id)
94
- end
95
- end
96
-
97
104
  def selecting_fields?(options)
98
105
  !options[:fields].nil?
99
106
  end
@@ -1,4 +1,6 @@
1
1
  # encoding: UTF-8
2
+ require 'mongo_mapper/plugins/keys/key'
3
+
2
4
  module MongoMapper
3
5
  module Plugins
4
6
  module Keys
@@ -1,61 +1,21 @@
1
1
  # encoding: UTF-8
2
+ require 'mongo_mapper/plugins/querying/decorator'
3
+ require 'mongo_mapper/plugins/querying/plucky_methods'
4
+
2
5
  module MongoMapper
3
6
  module Plugins
4
7
  module Querying
5
8
  module ClassMethods
6
- def find(*args)
7
- options = args.extract_options!
8
- return nil if args.size == 0
9
-
10
- if args.first.is_a?(Array) || args.size > 1
11
- find_some(args, options)
12
- else
13
- find_one(options.merge(:_id => args[0]))
14
- end
15
- end
16
-
17
- def find!(*args)
18
- options = args.extract_options!
19
- raise DocumentNotFound, "Couldn't find without an ID" if args.size == 0
9
+ include PluckyMethods
20
10
 
21
- if args.first.is_a?(Array) || args.size > 1
22
- find_some!(args, options)
23
- else
24
- find_one(options.merge(:_id => args[0])) ||
25
- raise(DocumentNotFound, "Document match #{options.inspect} does not exist
26
- in #{collection.name} collection")
27
- end
28
- end
29
-
30
- def find_each(options={})
31
- query(options).find_each.each { |doc| yield load(doc) }
11
+ def find_each(opts={})
12
+ super(opts).each { |doc| yield load(doc) }
32
13
  end
33
14
 
34
15
  def find_by_id(id)
35
16
  find_one(:_id => id)
36
17
  end
37
18
 
38
- def first(options={})
39
- find_one(options)
40
- end
41
-
42
- # All bets are off an actual order if you provide none.
43
- def last(options={})
44
- find_one(query(options).reverse.to_hash)
45
- end
46
-
47
- def all(options={})
48
- find_many(options)
49
- end
50
-
51
- def count(options={})
52
- query(options).count
53
- end
54
-
55
- def exists?(options={})
56
- !count(options).zero?
57
- end
58
-
59
19
  def first_or_create(args)
60
20
  first(args) || create(args.reject { |key, value| !key?(key) })
61
21
  end
@@ -97,30 +57,10 @@ module MongoMapper
97
57
  find_each(options) { |document| document.destroy }
98
58
  end
99
59
 
100
- def where(options={})
101
- query.where(options)
102
- end
103
-
104
- def fields(*args)
105
- query.fields(*args)
106
- end
107
-
108
- def limit(*args)
109
- query.limit(*args)
110
- end
111
-
112
- def skip(*args)
113
- query.skip(*args)
114
- end
115
-
116
- def sort(*args)
117
- query.sort(*args)
118
- end
119
-
120
60
  # @api private for now
121
61
  def query(options={})
122
62
  Plucky::Query.new(collection).tap do |query|
123
- query.extend(MongoMapper::Plugins::Querying::Decorator)
63
+ query.extend(Decorator)
124
64
  query.object_ids(object_id_keys)
125
65
  query.update(options)
126
66
  query.model(self)
@@ -3,7 +3,7 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Querying
5
5
  module Decorator
6
- include MongoMapper::Plugins::DynamicQuerying::ClassMethods
6
+ include DynamicQuerying::ClassMethods
7
7
 
8
8
  def model(model=nil)
9
9
  return @model if model.nil?
@@ -0,0 +1,15 @@
1
+ # encoding: UTF-8
2
+ require 'forwardable'
3
+
4
+ module MongoMapper
5
+ module Plugins
6
+ module Querying
7
+ module PluckyMethods
8
+ extend Forwardable
9
+ def_delegators :query, :where, :fields, :limit, :skip, :sort,
10
+ :count, :last, :first, :all, :paginate,
11
+ :find, :find!, :exists?, :exist?, :find_each
12
+ end
13
+ end
14
+ end
15
+ end
@@ -5,13 +5,13 @@ module MongoMapper
5
5
  def self.configure(model)
6
6
  model.class_eval do
7
7
  include Validatable
8
- extend Plugins::Validations::DocumentMacros
8
+ extend Validations::DocumentMacros
9
9
  end
10
10
  end
11
11
 
12
12
  module DocumentMacros
13
13
  def validates_uniqueness_of(*args)
14
- add_validations(args, MongoMapper::Plugins::Validations::ValidatesUniquenessOf)
14
+ add_validations(args, Validations::ValidatesUniquenessOf)
15
15
  end
16
16
  end
17
17
 
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module MongoMapper
3
- Version = '0.8.0'
3
+ Version = '0.8.1'
4
4
  end
File without changes
@@ -345,6 +345,45 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
345
345
  end
346
346
  end
347
347
 
348
+ context "sexy querying" do
349
+ should "work with where" do
350
+ @project1.statuses.where(:name => 'New').all.should == [@brand_new]
351
+ end
352
+
353
+ should "work with sort" do
354
+ @project1.statuses.sort(:name).all.should == [@complete, @brand_new]
355
+ end
356
+
357
+ should "work with limit" do
358
+ @project1.statuses.sort(:name).limit(1).all.should == [@complete]
359
+ end
360
+
361
+ should "work with skip" do
362
+ @project1.statuses.sort(:name).skip(1).all.should == [@brand_new]
363
+ end
364
+
365
+ should "work with fields" do
366
+ @project1.statuses.fields(:position).all.each do |status|
367
+ status.position.should_not be_nil
368
+ status.name.should be_nil
369
+ end
370
+ end
371
+
372
+ should "work with scopes" do
373
+ @project1.statuses.complete.all.should == [@complete]
374
+ end
375
+
376
+ should "work with methods on class that return query" do
377
+ @project1.statuses.by_position(1).first.should == @brand_new
378
+ end
379
+
380
+ should "not work with methods on class that do not return query" do
381
+ Status.class_eval { def self.foo; 'foo' end }
382
+ lambda { @project1.statuses.foo }.
383
+ should raise_error(NoMethodError)
384
+ end
385
+ end
386
+
348
387
  context "all" do
349
388
  should "work" do
350
389
  @project1.statuses.all(:order => "position asc").should == [@brand_new, @complete]
@@ -327,7 +327,7 @@ class IdentityMapTest < Test::Unit::TestCase
327
327
 
328
328
  should "return nil for document id not found in collection" do
329
329
  assert_in_map(@person)
330
- @person_class.find_by_id(1234).should be_nil
330
+ @person_class.find_by_id(BSON::ObjectID.new).should be_nil
331
331
  end
332
332
  end
333
333
 
@@ -342,13 +342,13 @@ class IdentityMapTest < Test::Unit::TestCase
342
342
  @person_class.first(:_id => @person.id, :select => 'name').should == @person
343
343
  @person_class.first(:_id => @person.id, 'fields' => ['name']).should == @person
344
344
  @person_class.last(:_id => @person.id, :select => 'name', :order => 'name').should == @person
345
- @person_class.find(@person.id, :select => 'name').should == @person
345
+ @person_class.fields(:name).find(@person.id).should == @person
346
346
  @person_class.all(:_id => @person.id, :select => 'name').should == [@person]
347
347
  assert_not_in_map(@person)
348
348
  end
349
349
 
350
350
  should "return nil if not found" do
351
- @person_class.find(1234, :select => 'name').should be_nil
351
+ @person_class.fields(:name).find(BSON::ObjectID.new).should be_nil
352
352
  end
353
353
  end
354
354
 
data/test/models.rb CHANGED
@@ -143,6 +143,12 @@ end
143
143
  class Status
144
144
  include MongoMapper::Document
145
145
 
146
+ scope :complete, where(:name => 'Complete')
147
+
148
+ def self.by_position(position)
149
+ where(:position => position)
150
+ end
151
+
146
152
  key :project_id, ObjectId
147
153
  key :target_id, ObjectId
148
154
  key :target_type, String
data/test/test_helper.rb CHANGED
@@ -1,19 +1,23 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../lib/mongo_mapper')
2
- require 'fileutils'
3
-
4
- gem 'jnunemaker-matchy', '0.4.0'
5
- gem 'shoulda', '2.10.2'
6
- gem 'json', '>= 1.2.3'
7
- gem 'timecop', '0.3.1'
8
- gem 'mocha', '0.9.8'
1
+ require 'rubygems'
2
+ gem 'activesupport', ENV['ACTIVE_SUPPORT_VERSION']
3
+ gem 'json', '~> 1.2.3'
4
+ gem 'jnunemaker-matchy', '~> 0.4.0'
5
+ gem 'shoulda', '~> 2.10.2'
6
+ gem 'timecop', '~> 0.3.1'
7
+ gem 'mocha', '~> 0.9.8'
9
8
 
9
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
10
+ require 'mongo_mapper'
11
+ require 'fileutils'
10
12
  require 'ostruct'
13
+ require 'pp'
14
+
15
+ require 'active_support/version'
16
+ require 'json'
17
+ require 'matchy'
11
18
  require 'shoulda'
12
19
  require 'timecop'
13
- require 'matchy'
14
20
  require 'mocha'
15
- require 'json'
16
- require 'pp'
17
21
 
18
22
  class Test::Unit::TestCase
19
23
  def Doc(name=nil, &block)
@@ -96,3 +100,5 @@ logger = Logger.new(log_dir + '/test.log')
96
100
  MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017, :logger => logger)
97
101
  MongoMapper.database = "mm-test-#{RUBY_VERSION.gsub('.', '-')}"
98
102
  MongoMapper.database.collections.each { |c| c.drop_indexes }
103
+
104
+ puts "\n--- Active Support Version: #{ActiveSupport::VERSION::STRING} ---\n"
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 8
8
- - 0
9
- version: 0.8.0
8
+ - 1
9
+ version: 0.8.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - John Nunemaker
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-16 00:00:00 -04:00
17
+ date: 2010-06-18 00:00:00 -04:00
18
18
  default_executable: mmconsole
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -55,8 +55,8 @@ dependencies:
55
55
  segments:
56
56
  - 0
57
57
  - 3
58
- - 0
59
- version: 0.3.0
58
+ - 1
59
+ version: 0.3.1
60
60
  type: :runtime
61
61
  version_requirements: *id003
62
62
  - !ruby/object:Gem::Dependency
@@ -64,7 +64,7 @@ dependencies:
64
64
  prerelease: false
65
65
  requirement: &id004 !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ">="
67
+ - - ~>
68
68
  - !ruby/object:Gem::Version
69
69
  segments:
70
70
  - 1
@@ -78,7 +78,7 @@ dependencies:
78
78
  prerelease: false
79
79
  requirement: &id005 !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ">="
81
+ - - ~>
82
82
  - !ruby/object:Gem::Version
83
83
  segments:
84
84
  - 0
@@ -92,7 +92,7 @@ dependencies:
92
92
  prerelease: false
93
93
  requirement: &id006 !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - ">="
95
+ - - ~>
96
96
  - !ruby/object:Gem::Version
97
97
  segments:
98
98
  - 2
@@ -106,7 +106,7 @@ dependencies:
106
106
  prerelease: false
107
107
  requirement: &id007 !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - ">="
109
+ - - ~>
110
110
  - !ruby/object:Gem::Version
111
111
  segments:
112
112
  - 0
@@ -120,7 +120,7 @@ dependencies:
120
120
  prerelease: false
121
121
  requirement: &id008 !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - ">="
123
+ - - ~>
124
124
  - !ruby/object:Gem::Version
125
125
  segments:
126
126
  - 0
@@ -199,6 +199,7 @@ files:
199
199
  - lib/mongo_mapper/plugins/persistence.rb
200
200
  - lib/mongo_mapper/plugins/protected.rb
201
201
  - lib/mongo_mapper/plugins/querying/decorator.rb
202
+ - lib/mongo_mapper/plugins/querying/plucky_methods.rb
202
203
  - lib/mongo_mapper/plugins/querying.rb
203
204
  - lib/mongo_mapper/plugins/rails.rb
204
205
  - lib/mongo_mapper/plugins/safe.rb
@@ -212,7 +213,7 @@ files:
212
213
  - lib/mongo_mapper/support/descendant_appends.rb
213
214
  - lib/mongo_mapper/version.rb
214
215
  - lib/mongo_mapper.rb
215
- - test/active_model_lint_test.rb
216
+ - test/_NOTE_ON_TESTING
216
217
  - test/functional/associations/test_belongs_to_polymorphic_proxy.rb
217
218
  - test/functional/associations/test_belongs_to_proxy.rb
218
219
  - test/functional/associations/test_in_array_proxy.rb
@@ -247,7 +248,7 @@ files:
247
248
  - test/functional/test_userstamps.rb
248
249
  - test/functional/test_validations.rb
249
250
  - test/models.rb
250
- - test/NOTE_ON_TESTING
251
+ - test/test_active_model_lint.rb
251
252
  - test/test_helper.rb
252
253
  - test/unit/associations/test_base.rb
253
254
  - test/unit/associations/test_proxy.rb