mongoid 0.8.9 → 0.8.10

Sign up to get free protection for your applications and to get access to all the features.
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