mongoid 0.8.9 → 0.8.10

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.9
1
+ 0.8.10
@@ -40,6 +40,7 @@ require "mongoid/associations/options"
40
40
  require "mongoid/attributes"
41
41
  require "mongoid/commands"
42
42
  require "mongoid/criteria"
43
+ require "mongoid/dynamic_finder"
43
44
  require "mongoid/extensions"
44
45
  require "mongoid/field"
45
46
  require "mongoid/finders"
@@ -5,13 +5,11 @@ module Mongoid #:nodoc:
5
5
 
6
6
  delegate :valid?, :to => :document
7
7
 
8
- attr_accessor :klass, :parent, :association_name
8
+ attr_accessor :parent, :options
9
9
 
10
10
  # Build a new object for the association.
11
11
  def build(attributes)
12
- @document = @klass.instantiate(attributes)
13
- @document.parentize(@parent, @association_name)
14
- @document.notify
12
+ @document = attributes.assimilate(@parent, @options)
15
13
  decorate!
16
14
  self
17
15
  end
@@ -30,10 +28,9 @@ module Mongoid #:nodoc:
30
28
  # All method calls on this object will then be delegated
31
29
  # to the internal document itself.
32
30
  def initialize(document, options)
33
- @klass, @parent, @association_name = options.klass, document, options.name
34
- attributes = document.attributes[options.name]
35
- @document = klass.instantiate(attributes || {})
36
- @document.parentize(document, options.name)
31
+ @parent, @options = document, options
32
+ attributes = @parent.attributes[options.name]
33
+ @document = (attributes || {}).assimilate(@parent, @options)
37
34
  decorate!
38
35
  end
39
36
 
@@ -101,10 +101,7 @@ module Mongoid #:nodoc:
101
101
  # objects of the type of class provided.
102
102
  def execute(klass = nil)
103
103
  @klass = klass if klass
104
- if type == :first
105
- attributes = klass.collection.find_one(@selector, @options.dup)
106
- return attributes ? @klass.instantiate(attributes) : nil
107
- else
104
+ if type == :all
108
105
  attributes = @klass.collection.find(@selector, @options.dup)
109
106
  if attributes
110
107
  @count = attributes.count
@@ -112,6 +109,9 @@ module Mongoid #:nodoc:
112
109
  else
113
110
  return []
114
111
  end
112
+ else
113
+ attributes = @klass.collection.find_one(@selector, @options.dup)
114
+ return attributes ? @klass.instantiate(attributes) : nil
115
115
  end
116
116
  end
117
117
 
@@ -101,11 +101,6 @@ module Mongoid #:nodoc:
101
101
  before_save :generate_key
102
102
  end
103
103
 
104
- # Find the last +Document+ in the collection by reverse id
105
- def last
106
- find(:first, :conditions => {}, :sort => [[:_id, :asc]])
107
- end
108
-
109
104
  # Returns the primary key field of the +Document+
110
105
  def primary_key
111
106
  @primary_key
@@ -0,0 +1,64 @@
1
+ module Mongoid #:nodoc:
2
+ class DynamicFinder
3
+ # Regex for standard dynamic finder methods.
4
+ FINDER = /^find_(all_by|last_by|by)_([_a-zA-Z]\w*)$/
5
+ # Regex for finder methods that create objects if nothing found.
6
+ CREATOR = /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/
7
+
8
+ attr_reader :conditions, :finder
9
+
10
+ # Creates a new DynamicFinder given the supplied method name. This parses
11
+ # the name and sets up the appropriate finder type and attribute names in
12
+ # order to perform the search.
13
+ #
14
+ # Options:
15
+ #
16
+ # method: The name of the dynamic finder method.
17
+ #
18
+ # Example:
19
+ #
20
+ # <tt>DynamicFinder.new(:find_by_title_and_age)</tt>
21
+ def initialize(method, *args)
22
+ @finder, @args = :first, args
23
+ case method.to_s
24
+ when FINDER
25
+ @finder = :all if $1 == "all_by"
26
+ @finder = :last if $1 == "last_by"
27
+ names = $2
28
+ when CREATOR then
29
+ @creator = ($1 == "initialize") ? :instantiate : :create
30
+ names = $2
31
+ else
32
+ @finder = nil
33
+ end
34
+ @attributes = names && names.split("_and_")
35
+ generate_conditions
36
+ end
37
+
38
+ # Will create a new +Document+ based on the type of creator keyword in the
39
+ # method, given the supplied class.
40
+ #
41
+ # Options:
42
+ #
43
+ # klass: The +Document+ class to be instantiated.
44
+ #
45
+ # Example:
46
+ #
47
+ # <tt>finder.create(Person)</tt>
48
+ def create(klass)
49
+ klass.send(@creator, @conditions) if @creator
50
+ end
51
+
52
+ protected
53
+ def generate_conditions
54
+ if @attributes
55
+ @conditions = {}.with_indifferent_access
56
+ @attributes.each_with_index do |attr, index|
57
+ attr = "_id" if attr == "id"
58
+ @conditions[attr] = @args[index]
59
+ end
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -18,7 +18,7 @@ module Mongoid #:nodoc:
18
18
  # Returns: The child +Document+.
19
19
  def assimilate(parent, options)
20
20
  klass = options.klass
21
- child = klass.new(self)
21
+ child = klass.instantiate(self)
22
22
  child.assimilate(parent, options)
23
23
  end
24
24
  end
@@ -36,11 +36,6 @@ module Mongoid #:nodoc:
36
36
  Criteria.translate(*args).execute(self)
37
37
  end
38
38
 
39
- # Find a +Document+ by its id.
40
- def find_by_id(id)
41
- find(id)
42
- end
43
-
44
39
  # Find the first +Document+ given the conditions.
45
40
  #
46
41
  # Options:
@@ -52,6 +47,36 @@ module Mongoid #:nodoc:
52
47
  find(:first, *args)
53
48
  end
54
49
 
50
+ # Find the last +Document+ given the conditions.
51
+ #
52
+ # Options:
53
+ #
54
+ # args: A +Hash+ with a conditions key and other options
55
+ #
56
+ # <tt>Person.last(:conditions => { :attribute => "value" })</tt>
57
+ def last(*args)
58
+ return find(:last, :conditions => {}, :sort => [[:_id, :desc]]) if args.empty?
59
+ return find(:last, *args) unless args.empty?
60
+ end
61
+
62
+ # Will execute a +Criteria+ based on the +DynamicFinder+ that gets
63
+ # generated.
64
+ #
65
+ # Options:
66
+ #
67
+ # name: The finder method name
68
+ # args: The arguments to pass to the method.
69
+ #
70
+ # Example:
71
+ #
72
+ # <tt>Person.find_all_by_title_and_age("Sir", 30)</tt>
73
+ def method_missing(name, *args)
74
+ dyna = DynamicFinder.new(name, *args)
75
+ finder, conditions = dyna.finder, dyna.conditions
76
+ results = Criteria.translate(finder, :conditions => conditions).execute(self)
77
+ results ? results : dyna.create(self)
78
+ end
79
+
55
80
  # Find all documents in paginated fashion given the supplied arguments.
56
81
  # If no parameters are passed just default to offset 0 and limit 20.
57
82
  #
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongoid}
8
- s.version = "0.8.9"
8
+ s.version = "0.8.10"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Durran Jordan"]
12
- s.date = %q{2009-11-26}
12
+ s.date = %q{2009-11-27}
13
13
  s.email = %q{durran@gmail.com}
14
14
  s.extra_rdoc_files = [
15
15
  "README.textile"
@@ -40,6 +40,7 @@ Gem::Specification.new do |s|
40
40
  "lib/mongoid/commands/validate.rb",
41
41
  "lib/mongoid/criteria.rb",
42
42
  "lib/mongoid/document.rb",
43
+ "lib/mongoid/dynamic_finder.rb",
43
44
  "lib/mongoid/extensions.rb",
44
45
  "lib/mongoid/extensions/array/assimilation.rb",
45
46
  "lib/mongoid/extensions/array/conversions.rb",
@@ -85,6 +86,7 @@ Gem::Specification.new do |s|
85
86
  "spec/unit/mongoid/commands_spec.rb",
86
87
  "spec/unit/mongoid/criteria_spec.rb",
87
88
  "spec/unit/mongoid/document_spec.rb",
89
+ "spec/unit/mongoid/dynamic_finder_spec.rb",
88
90
  "spec/unit/mongoid/extensions/array/assimilation_spec.rb",
89
91
  "spec/unit/mongoid/extensions/array/conversions_spec.rb",
90
92
  "spec/unit/mongoid/extensions/array/parentization_spec.rb",
@@ -132,6 +134,7 @@ Gem::Specification.new do |s|
132
134
  "spec/unit/mongoid/commands_spec.rb",
133
135
  "spec/unit/mongoid/criteria_spec.rb",
134
136
  "spec/unit/mongoid/document_spec.rb",
137
+ "spec/unit/mongoid/dynamic_finder_spec.rb",
135
138
  "spec/unit/mongoid/extensions/array/assimilation_spec.rb",
136
139
  "spec/unit/mongoid/extensions/array/conversions_spec.rb",
137
140
  "spec/unit/mongoid/extensions/array/parentization_spec.rb",
@@ -64,6 +64,45 @@ describe Mongoid::Document do
64
64
  end
65
65
  end
66
66
 
67
+ context "using dynamic finders" do
68
+
69
+ before do
70
+ @person = Person.create(:title => "Mr", :age => 25)
71
+ end
72
+
73
+ context "finding by a single attribute" do
74
+
75
+ it "returns found documents" do
76
+ Person.find_by_title("Mr").should == @person
77
+ end
78
+
79
+ end
80
+
81
+ context "finding by multiple attributes" do
82
+
83
+ it "returns found documents" do
84
+ Person.find_by_title_and_age("Mr", 25).should == @person
85
+ end
86
+
87
+ end
88
+
89
+ context "finding all by a single attribute" do
90
+
91
+ it "returns found documents" do
92
+ Person.find_all_by_title("Mr").should == [@person]
93
+ end
94
+
95
+ end
96
+
97
+ context "finding all by multiple attributes" do
98
+
99
+ it "returns found documents" do
100
+ Person.find_all_by_title_and_age("Mr", 25).should == [@person]
101
+ end
102
+
103
+ end
104
+ end
105
+
67
106
  describe "#find" do
68
107
 
69
108
  before do
@@ -0,0 +1,145 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../spec_helper.rb"))
2
+
3
+ describe Mongoid::DynamicFinder do
4
+
5
+ describe "#conditions" do
6
+
7
+ before do
8
+ @finder = Mongoid::DynamicFinder.new(:find_by_title_and_age, "Sir", 30)
9
+ @conditions = { "title" => "Sir", "age" => 30 }
10
+ end
11
+
12
+ it "returns the conditions hash for the criteria" do
13
+ @finder.conditions.should == @conditions
14
+ end
15
+
16
+ context "when id is an attribute" do
17
+
18
+ before do
19
+ @finder = Mongoid::DynamicFinder.new(:find_by_id, "5")
20
+ @conditions = { "_id" => "5" }
21
+ end
22
+
23
+ it "converts to _id" do
24
+ @finder.conditions.should == @conditions
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ describe "#create" do
32
+
33
+ context "when initializing" do
34
+
35
+ before do
36
+ @finder = Mongoid::DynamicFinder.new(:find_or_initialize_by_title_and_age, "Sir", 30)
37
+ end
38
+
39
+ it "instantiates a new document" do
40
+ person = @finder.create(Person)
41
+ person.title.should == "Sir"
42
+ person.age.should == 30
43
+ end
44
+
45
+ end
46
+
47
+ context "when creating" do
48
+
49
+ before do
50
+ @finder = Mongoid::DynamicFinder.new(:find_or_create_by_title_and_age, "Sir", 30)
51
+ @person = stub
52
+ end
53
+
54
+ it "creates a new document" do
55
+ Person.expects(:create).with(@finder.conditions).returns(@person)
56
+ person = @finder.create(Person)
57
+ person.should == @person
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ describe ".initialize" do
65
+
66
+ context "when find_by*" do
67
+
68
+ before do
69
+ @finder = Mongoid::DynamicFinder.new(:find_by_title_and_age, "Sir", 30)
70
+ end
71
+
72
+ it "sets a first finder and attributes" do
73
+ @finder.finder.should == :first
74
+ @finder.conditions.should == { "title" => "Sir", "age" => 30 }
75
+ end
76
+
77
+ end
78
+
79
+ context "when find_all_by*" do
80
+
81
+ before do
82
+ @finder = Mongoid::DynamicFinder.new(:find_all_by_title_and_age, "Sir", 30)
83
+ end
84
+
85
+ it "sets an all finder and attributes" do
86
+ @finder.finder.should == :all
87
+ @finder.conditions.should == { "title" => "Sir", "age" => 30 }
88
+ end
89
+
90
+ end
91
+
92
+ context "when find_last_by*" do
93
+
94
+ before do
95
+ @finder = Mongoid::DynamicFinder.new(:find_last_by_title_and_age, "Sir", 30)
96
+ end
97
+
98
+ it "sets a last finder and attributes" do
99
+ @finder.finder.should == :last
100
+ @finder.conditions.should == { "title" => "Sir", "age" => 30 }
101
+ end
102
+
103
+ end
104
+
105
+ context "when find_or_initialize_by*" do
106
+
107
+ before do
108
+ @finder = Mongoid::DynamicFinder.new(:find_or_initialize_by_title_and_age, "Sir", 30)
109
+ end
110
+
111
+ it "sets a first finder with attributes or a new" do
112
+ @finder.finder.should == :first
113
+ @finder.conditions.should == { "title" => "Sir", "age" => 30 }
114
+ end
115
+
116
+ end
117
+
118
+ context "when find_or_create_by*" do
119
+
120
+ before do
121
+ @finder = Mongoid::DynamicFinder.new(:find_or_create_by_title_and_age, "Sir", 30)
122
+ end
123
+
124
+ it "sets a first finder with attributes or a create" do
125
+ @finder.finder.should == :first
126
+ @finder.conditions.should == { "title" => "Sir", "age" => 30 }
127
+ end
128
+
129
+ end
130
+
131
+ context "when invalid finder name" do
132
+
133
+ before do
134
+ @finder = Mongoid::DynamicFinder.new(:bleh)
135
+ end
136
+
137
+ it "sets a nil finder" do
138
+ @finder.finder.should be_nil
139
+ end
140
+
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -137,13 +137,13 @@ describe Mongoid::Finders do
137
137
  end
138
138
 
139
139
  it "delegates to find with an id parameter" do
140
- Mongoid::Criteria.expects(:translate).with("1").returns(@criteria)
140
+ Mongoid::Criteria.expects(:translate).with(:first, :conditions => { "_id" => "1" }).returns(@criteria)
141
141
  Person.find_by_id("1")
142
142
  end
143
143
 
144
144
  end
145
145
 
146
- describe "#first" do
146
+ describe ".first" do
147
147
 
148
148
  before do
149
149
  @attributes = { "age" => 100 }
@@ -173,7 +173,7 @@ describe Mongoid::Finders do
173
173
 
174
174
  before do
175
175
  @attributes = { :_id => 1, :title => "Sir" }
176
- @collection.expects(:find_one).with({}, :sort => [[:_id, :asc]]).returns(@attributes)
176
+ @collection.expects(:find_one).with({}, :sort => [[:_id, :desc]]).returns(@attributes)
177
177
  end
178
178
 
179
179
  it "finds the last document by the id" do
@@ -182,6 +182,59 @@ describe Mongoid::Finders do
182
182
 
183
183
  end
184
184
 
185
+ describe ".method_missing" do
186
+
187
+ context "with a finder method name" do
188
+
189
+ before do
190
+ @criteria = stub
191
+ @document = stub
192
+ @conditions = { "title" => "Sir", "age" => 30 }
193
+ end
194
+
195
+ it "executes the finder" do
196
+ Mongoid::Criteria.expects(:translate).with(:first, :conditions => @conditions).returns(@criteria)
197
+ @criteria.expects(:execute).with(Person).returns(@document)
198
+ Person.find_by_title_and_age("Sir", 30)
199
+ end
200
+
201
+ end
202
+
203
+ context "with a finder or creation method name" do
204
+
205
+ before do
206
+ @criteria = stub
207
+ @document = stub
208
+ @conditions = { "title" => "Sir", "age" => 30 }
209
+ end
210
+
211
+ context "when document is found" do
212
+
213
+ it "returns the document" do
214
+ Mongoid::Criteria.expects(:translate).with(:first, :conditions => @conditions).returns(@criteria)
215
+ @criteria.expects(:execute).with(Person).returns(@document)
216
+ Person.find_or_initialize_by_title_and_age("Sir", 30).should == @document
217
+ end
218
+
219
+ end
220
+
221
+ context "when document is not found" do
222
+
223
+ it "instantiates a new document" do
224
+ Mongoid::Criteria.expects(:translate).with(:first, :conditions => @conditions).returns(@criteria)
225
+ @criteria.expects(:execute).with(Person).returns(nil)
226
+ new_doc = Person.find_or_initialize_by_title_and_age("Sir", 30)
227
+ new_doc.new_record?.should be_true
228
+ new_doc.title.should == "Sir"
229
+ new_doc.age.should == 30
230
+ end
231
+
232
+ end
233
+
234
+ end
235
+
236
+ end
237
+
185
238
  describe ".paginate" do
186
239
 
187
240
  before do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.9
4
+ version: 0.8.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Durran Jordan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-26 00:00:00 -05:00
12
+ date: 2009-11-27 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -96,6 +96,7 @@ files:
96
96
  - lib/mongoid/commands/validate.rb
97
97
  - lib/mongoid/criteria.rb
98
98
  - lib/mongoid/document.rb
99
+ - lib/mongoid/dynamic_finder.rb
99
100
  - lib/mongoid/extensions.rb
100
101
  - lib/mongoid/extensions/array/assimilation.rb
101
102
  - lib/mongoid/extensions/array/conversions.rb
@@ -141,6 +142,7 @@ files:
141
142
  - spec/unit/mongoid/commands_spec.rb
142
143
  - spec/unit/mongoid/criteria_spec.rb
143
144
  - spec/unit/mongoid/document_spec.rb
145
+ - spec/unit/mongoid/dynamic_finder_spec.rb
144
146
  - spec/unit/mongoid/extensions/array/assimilation_spec.rb
145
147
  - spec/unit/mongoid/extensions/array/conversions_spec.rb
146
148
  - spec/unit/mongoid/extensions/array/parentization_spec.rb
@@ -210,6 +212,7 @@ test_files:
210
212
  - spec/unit/mongoid/commands_spec.rb
211
213
  - spec/unit/mongoid/criteria_spec.rb
212
214
  - spec/unit/mongoid/document_spec.rb
215
+ - spec/unit/mongoid/dynamic_finder_spec.rb
213
216
  - spec/unit/mongoid/extensions/array/assimilation_spec.rb
214
217
  - spec/unit/mongoid/extensions/array/conversions_spec.rb
215
218
  - spec/unit/mongoid/extensions/array/parentization_spec.rb