djsun-mongo_mapper 0.5.0.1

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.
Files changed (71) hide show
  1. data/.gitignore +8 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +39 -0
  4. data/Rakefile +87 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +55 -0
  7. data/lib/mongo_mapper/associations/base.rb +83 -0
  8. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  9. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +22 -0
  10. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +27 -0
  11. data/lib/mongo_mapper/associations/many_documents_proxy.rb +116 -0
  12. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  13. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +67 -0
  14. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +11 -0
  15. data/lib/mongo_mapper/associations/many_proxy.rb +6 -0
  16. data/lib/mongo_mapper/associations/proxy.rb +74 -0
  17. data/lib/mongo_mapper/associations.rb +86 -0
  18. data/lib/mongo_mapper/callbacks.rb +106 -0
  19. data/lib/mongo_mapper/document.rb +308 -0
  20. data/lib/mongo_mapper/dynamic_finder.rb +35 -0
  21. data/lib/mongo_mapper/embedded_document.rb +354 -0
  22. data/lib/mongo_mapper/finder_options.rb +94 -0
  23. data/lib/mongo_mapper/key.rb +32 -0
  24. data/lib/mongo_mapper/observing.rb +50 -0
  25. data/lib/mongo_mapper/pagination.rb +51 -0
  26. data/lib/mongo_mapper/rails_compatibility/document.rb +15 -0
  27. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +27 -0
  28. data/lib/mongo_mapper/save_with_validation.rb +19 -0
  29. data/lib/mongo_mapper/serialization.rb +55 -0
  30. data/lib/mongo_mapper/serializers/json_serializer.rb +92 -0
  31. data/lib/mongo_mapper/support.rb +171 -0
  32. data/lib/mongo_mapper/validations.rb +69 -0
  33. data/lib/mongo_mapper.rb +95 -0
  34. data/mongo_mapper.gemspec +156 -0
  35. data/specs.watchr +32 -0
  36. data/test/NOTE_ON_TESTING +1 -0
  37. data/test/custom_matchers.rb +48 -0
  38. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +55 -0
  39. data/test/functional/associations/test_belongs_to_proxy.rb +49 -0
  40. data/test/functional/associations/test_many_documents_as_proxy.rb +244 -0
  41. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +132 -0
  42. data/test/functional/associations/test_many_embedded_proxy.rb +174 -0
  43. data/test/functional/associations/test_many_polymorphic_proxy.rb +297 -0
  44. data/test/functional/associations/test_many_proxy.rb +331 -0
  45. data/test/functional/test_associations.rb +44 -0
  46. data/test/functional/test_binary.rb +18 -0
  47. data/test/functional/test_callbacks.rb +85 -0
  48. data/test/functional/test_document.rb +964 -0
  49. data/test/functional/test_embedded_document.rb +97 -0
  50. data/test/functional/test_logger.rb +20 -0
  51. data/test/functional/test_pagination.rb +87 -0
  52. data/test/functional/test_rails_compatibility.rb +30 -0
  53. data/test/functional/test_validations.rb +279 -0
  54. data/test/models.rb +169 -0
  55. data/test/test_helper.rb +30 -0
  56. data/test/unit/serializers/test_json_serializer.rb +193 -0
  57. data/test/unit/test_association_base.rb +144 -0
  58. data/test/unit/test_document.rb +165 -0
  59. data/test/unit/test_dynamic_finder.rb +125 -0
  60. data/test/unit/test_embedded_document.rb +643 -0
  61. data/test/unit/test_finder_options.rb +193 -0
  62. data/test/unit/test_key.rb +175 -0
  63. data/test/unit/test_mongomapper.rb +28 -0
  64. data/test/unit/test_observing.rb +101 -0
  65. data/test/unit/test_pagination.rb +109 -0
  66. data/test/unit/test_rails_compatibility.rb +39 -0
  67. data/test/unit/test_serializations.rb +52 -0
  68. data/test/unit/test_support.rb +272 -0
  69. data/test/unit/test_time_zones.rb +40 -0
  70. data/test/unit/test_validations.rb +503 -0
  71. metadata +207 -0
@@ -0,0 +1,193 @@
1
+ require 'test_helper'
2
+
3
+ class JsonSerializationTest < Test::Unit::TestCase
4
+ class Tag
5
+ include MongoMapper::EmbeddedDocument
6
+ key :name, String
7
+ end
8
+
9
+ class Contact
10
+ include MongoMapper::Document
11
+ key :name, String
12
+ key :age, Integer
13
+ key :created_at, Time
14
+ key :awesome, Boolean
15
+ key :preferences, Hash
16
+ key :hiding, String
17
+
18
+ many :tags, :class_name => 'JsonSerializationTest::Tag'
19
+ end
20
+
21
+ def setup
22
+ Contact.include_root_in_json = false
23
+ @contact = Contact.new(
24
+ :name => 'Konata Izumi',
25
+ :age => 16,
26
+ :created_at => Time.utc(2006, 8, 1),
27
+ :awesome => true,
28
+ :preferences => { :shows => 'anime' }
29
+ )
30
+ end
31
+
32
+ should "include demodulized root" do
33
+ Contact.include_root_in_json = true
34
+ assert_match %r{^\{"contact": \{}, @contact.to_json
35
+ end
36
+
37
+ should "encode all encodable attributes" do
38
+ json = @contact.to_json
39
+
40
+ assert_no_match %r{"_id"}, json
41
+ assert_match %r{"name":"Konata Izumi"}, json
42
+ assert_match %r{"age":16}, json
43
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
44
+ assert_match %r{"awesome":true}, json
45
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
46
+ assert_match %r{"hiding":null}, json
47
+ end
48
+
49
+ should "allow attribute filtering with only" do
50
+ json = @contact.to_json(:only => [:name, :age])
51
+
52
+ assert_no_match %r{"_id"}, json
53
+ assert_match %r{"name":"Konata Izumi"}, json
54
+ assert_match %r{"age":16}, json
55
+ assert_no_match %r{"awesome"}, json
56
+ assert_no_match %r{"created_at"}, json
57
+ assert_no_match %r{"preferences"}, json
58
+ assert_no_match %r{"hiding"}, json
59
+ end
60
+
61
+ should "allow attribute filtering with except" do
62
+ json = @contact.to_json(:except => [:name, :age])
63
+
64
+ assert_no_match %r{"_id"}, json
65
+ assert_no_match %r{"name"}, json
66
+ assert_no_match %r{"age"}, json
67
+ assert_match %r{"awesome"}, json
68
+ assert_match %r{"created_at"}, json
69
+ assert_match %r{"preferences"}, json
70
+ assert_match %r{"hiding"}, json
71
+ end
72
+
73
+ context "_id key" do
74
+ should "not be included by default" do
75
+ json = @contact.to_json
76
+ assert_no_match %r{"_id":}, json
77
+ end
78
+
79
+ should "not be included even if :except is used" do
80
+ json = @contact.to_json(:except => :name)
81
+ assert_no_match %r{"_id":}, json
82
+ end
83
+ end
84
+
85
+ context "id method" do
86
+ setup do
87
+ def @contact.label; "Has cheezburger"; end
88
+ def @contact.favorite_quote; "Constraints are liberating"; end
89
+ end
90
+
91
+ should "be included by default" do
92
+ json = @contact.to_json
93
+ assert_match %r{"id"}, json
94
+ end
95
+
96
+ should "be included when single method included" do
97
+ json = @contact.to_json(:methods => :label)
98
+ assert_match %r{"id"}, json
99
+ assert_match %r{"label":"Has cheezburger"}, json
100
+ assert_match %r{"name":"Konata Izumi"}, json
101
+ assert_no_match %r{"favorite_quote":"Constraints are liberating"}, json
102
+ end
103
+
104
+ should "be included when multiple methods included" do
105
+ json = @contact.to_json(:methods => [:label, :favorite_quote])
106
+ assert_match %r{"id"}, json
107
+ assert_match %r{"label":"Has cheezburger"}, json
108
+ assert_match %r{"favorite_quote":"Constraints are liberating"}, json
109
+ assert_match %r{"name":"Konata Izumi"}, json
110
+ end
111
+
112
+ should "not be included if :only is present" do
113
+ json = @contact.to_json(:only => :name)
114
+ assert_no_match %r{"id":}, json
115
+ end
116
+ end
117
+
118
+ context "including methods" do
119
+ setup do
120
+ def @contact.label; "Has cheezburger"; end
121
+ def @contact.favorite_quote; "Constraints are liberating"; end
122
+ end
123
+
124
+ should "include single method" do
125
+ json = @contact.to_json(:methods => :label)
126
+ assert_match %r{"label":"Has cheezburger"}, json
127
+ end
128
+
129
+ should "include multiple methods" do
130
+ json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
131
+ assert_match %r{"label":"Has cheezburger"}, json
132
+ assert_match %r{"favorite_quote":"Constraints are liberating"}, json
133
+ assert_match %r{"name":"Konata Izumi"}, json
134
+ assert_no_match %r{"age":16}, json
135
+ assert_no_match %r{"awesome"}, json
136
+ assert_no_match %r{"created_at"}, json
137
+ assert_no_match %r{"preferences"}, json
138
+ end
139
+ end
140
+
141
+ context "array of records" do
142
+ setup do
143
+ @contacts = [
144
+ Contact.new(:name => 'David', :age => 39),
145
+ Contact.new(:name => 'Mary', :age => 14)
146
+ ]
147
+ end
148
+
149
+ should "allow attribute filtering with only" do
150
+ json = @contacts.to_json(:only => :name)
151
+ assert_match %r{\{"name":"David"\}}, json
152
+ assert_match %r{\{"name":"Mary"\}}, json
153
+ end
154
+
155
+ should "allow attribute filtering with except" do
156
+ json = @contacts.to_json(:except => [:name, :preferences, :awesome, :created_at, :updated_at])
157
+ assert_match %r{"age":39}, json
158
+ assert_match %r{"age":14}, json
159
+ assert_no_match %r{"name":}, json
160
+ assert_no_match %r{"preferences":}, json
161
+ assert_no_match %r{"awesome":}, json
162
+ assert_no_match %r{"created_at":}, json
163
+ assert_no_match %r{"updated_at":}, json
164
+ end
165
+ end
166
+
167
+ should "allow options for hash of records" do
168
+ contacts = {
169
+ 1 => Contact.new(:name => 'David', :age => 39),
170
+ 2 => Contact.new(:name => 'Mary', :age => 14)
171
+ }
172
+ json = contacts.to_json(:only => [1, :name])
173
+ assert_match %r{"1":}, json
174
+ assert_match %r{\{"name":"David"\}}, json
175
+ assert_no_match %r{"2":}, json
176
+ end
177
+
178
+ should "include embedded attributes" do
179
+ contact = Contact.new(:name => 'John', :age => 27)
180
+ contact.tags = [Tag.new(:name => 'awesome'), Tag.new(:name => 'ruby')]
181
+ json = contact.to_json
182
+ assert_match %r{"tags":}, json
183
+ assert_match %r{"name":"awesome"}, json
184
+ assert_match %r{"name":"ruby"}, json
185
+ end
186
+
187
+ should "include dynamic attributes" do
188
+ contact = Contact.new(:name => 'John', :age => 27, :foo => 'bar')
189
+ contact['smell'] = 'stinky'
190
+ json = contact.to_json
191
+ assert_match %r{"smell":"stinky"}, json
192
+ end
193
+ end
@@ -0,0 +1,144 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class FooMonster; end
5
+
6
+ class AssociationBaseTest < Test::Unit::TestCase
7
+ include MongoMapper::Associations
8
+
9
+ should "initialize with type and name" do
10
+ base = Base.new(:many, :foos)
11
+ base.type.should == :many
12
+ base.name.should == :foos
13
+ end
14
+
15
+ should "also allow options when initializing" do
16
+ base = Base.new(:many, :foos, :polymorphic => true)
17
+ base.options[:polymorphic].should be_true
18
+ end
19
+
20
+ context "class_name" do
21
+ should "work for belongs_to" do
22
+ Base.new(:belongs_to, :user).class_name.should == 'User'
23
+ end
24
+
25
+ should "work for many" do
26
+ Base.new(:many, :smart_people).class_name.should == 'SmartPerson'
27
+ end
28
+
29
+ should "be changeable using class_name option" do
30
+ base = Base.new(:many, :smart_people, :class_name => 'IntelligentPerson')
31
+ base.class_name.should == 'IntelligentPerson'
32
+ end
33
+ end
34
+
35
+ context "klass" do
36
+ should "be class_name constantized" do
37
+ Base.new(:belongs_to, :foo_monster).klass.should == FooMonster
38
+ end
39
+ end
40
+
41
+ context "many?" do
42
+ should "be true if many" do
43
+ Base.new(:many, :foos).many?.should be_true
44
+ end
45
+
46
+ should "be false if not many" do
47
+ Base.new(:belongs_to, :foo).many?.should be_false
48
+ end
49
+ end
50
+
51
+ context "belongs_to?" do
52
+ should "be true if belongs_to" do
53
+ Base.new(:belongs_to, :foo).belongs_to?.should be_true
54
+ end
55
+
56
+ should "be false if not belongs_to" do
57
+ Base.new(:many, :foos).belongs_to?.should be_false
58
+ end
59
+ end
60
+
61
+ context "polymorphic?" do
62
+ should "be true if polymorphic" do
63
+ Base.new(:many, :foos, :polymorphic => true).polymorphic?.should be_true
64
+ end
65
+
66
+ should "be false if not polymorphic" do
67
+ Base.new(:many, :bars).polymorphic?.should be_false
68
+ end
69
+ end
70
+
71
+ context "type_key_name" do
72
+ should "be _type for many" do
73
+ Base.new(:many, :foos).type_key_name.should == '_type'
74
+ end
75
+
76
+ should "be association name _ type for belongs_to" do
77
+ Base.new(:belongs_to, :foo).type_key_name.should == 'foo_type'
78
+ end
79
+ end
80
+
81
+ context "foreign_key" do
82
+ should "default to assocation_name_id" do
83
+ base = Base.new(:belongs_to, :foo)
84
+ base.foreign_key.should == 'foo_id'
85
+ end
86
+
87
+ should "be overridable with :foreign_key option" do
88
+ base = Base.new(:belongs_to, :foo, :foreign_key => 'foobar_id')
89
+ base.foreign_key.should == 'foobar_id'
90
+ end
91
+ end
92
+
93
+ should "have ivar that is association name" do
94
+ Base.new(:belongs_to, :foo).ivar.should == '@_foo'
95
+ end
96
+
97
+ context "embeddable?" do
98
+ should "be true if class is embeddable" do
99
+ base = Base.new(:many, :medias)
100
+ base.embeddable?.should be_true
101
+ end
102
+
103
+ should "be false if class is not embeddable" do
104
+ base = Base.new(:many, :statuses)
105
+ base.embeddable?.should be_false
106
+
107
+ base = Base.new(:belongs_to, :project)
108
+ base.embeddable?.should be_false
109
+ end
110
+ end
111
+
112
+ context "proxy_class" do
113
+ should "be ManyProxy for many" do
114
+ base = Base.new(:many, :statuses)
115
+ base.proxy_class.should == ManyProxy
116
+ end
117
+
118
+ should "be ManyPolymorphicProxy for polymorphic many" do
119
+ base = Base.new(:many, :messages, :polymorphic => true)
120
+ base.proxy_class.should == ManyPolymorphicProxy
121
+ end
122
+
123
+ should "be ManyEmbeddedProxy for many embedded" do
124
+ base = Base.new(:many, :medias)
125
+ base.proxy_class.should == ManyEmbeddedProxy
126
+ end
127
+
128
+ should "be ManyEmbeddedPolymorphicProxy for polymorphic many embedded" do
129
+ base = Base.new(:many, :medias, :polymorphic => true)
130
+ base.proxy_class.should == ManyEmbeddedPolymorphicProxy
131
+ end
132
+
133
+ should "be BelongsToProxy for belongs_to" do
134
+ base = Base.new(:belongs_to, :project)
135
+ base.proxy_class.should == BelongsToProxy
136
+ end
137
+
138
+ should "be BelongsToPolymorphicProxy for polymorphic belongs_to" do
139
+ base = Base.new(:belongs_to, :target, :polymorphic => true)
140
+ base.proxy_class.should == BelongsToPolymorphicProxy
141
+ end
142
+ end
143
+
144
+ end
@@ -0,0 +1,165 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class DocumentTest < Test::Unit::TestCase
5
+ context "The Document Class" do
6
+ setup do
7
+ @document = Class.new do
8
+ include MongoMapper::Document
9
+ set_collection_name 'test'
10
+ end
11
+ end
12
+
13
+ should "track its descendants" do
14
+ MongoMapper::Document.descendants.should include(@document)
15
+ end
16
+
17
+ should "use default database by default" do
18
+ @document.database.should == MongoMapper.database
19
+ end
20
+
21
+ should "have a connection" do
22
+ @document.connection.should be_instance_of(Mongo::Connection)
23
+ end
24
+
25
+ should "allow setting different connection without affecting the default" do
26
+ conn = Mongo::Connection.new
27
+ @document.connection conn
28
+ @document.connection.should == conn
29
+ @document.connection.should_not == MongoMapper.connection
30
+ end
31
+
32
+ should "allow setting a different database without affecting the default" do
33
+ @document.database AlternateDatabase
34
+ @document.database.name.should == AlternateDatabase
35
+
36
+ another_document = Class.new do
37
+ include MongoMapper::Document
38
+ set_collection_name 'test'
39
+ end
40
+ another_document.database.should == MongoMapper.database
41
+ end
42
+
43
+ should "default collection name to class name tableized" do
44
+ class Item
45
+ include MongoMapper::Document
46
+ end
47
+
48
+ Item.collection.should be_instance_of(Mongo::Collection)
49
+ Item.collection.name.should == 'items'
50
+ end
51
+
52
+ should "allow setting the collection name" do
53
+ @document.set_collection_name('foobar')
54
+ @document.collection.should be_instance_of(Mongo::Collection)
55
+ @document.collection.name.should == 'foobar'
56
+ end
57
+ end # Document class
58
+
59
+ context "Documents that inherit from other documents" do
60
+ should "default collection name to inherited class" do
61
+ Message.collection_name.should == 'messages'
62
+ Enter.collection_name.should == 'messages'
63
+ Exit.collection_name.should == 'messages'
64
+ Chat.collection_name.should == 'messages'
65
+ end
66
+
67
+ should "default associations to inherited class" do
68
+ Message.associations.keys.should include("room")
69
+ Enter.associations.keys.should include("room")
70
+ Exit.associations.keys.should include("room")
71
+ Chat.associations.keys.should include("room")
72
+ end
73
+
74
+ should "track subclasses" do
75
+ Message.subclasses.should == [Enter, Exit, Chat]
76
+ end
77
+ end
78
+
79
+ context "An instance of a document" do
80
+ setup do
81
+ @document = Class.new do
82
+ include MongoMapper::Document
83
+ set_collection_name 'test'
84
+
85
+ key :name, String
86
+ key :age, Integer
87
+ end
88
+ @document.collection.clear
89
+ end
90
+
91
+ should "have access to the class's collection" do
92
+ doc = @document.new
93
+ doc.collection.should == @document.collection
94
+ end
95
+
96
+ should "use default values if defined for keys" do
97
+ @document.key :active, Boolean, :default => true
98
+
99
+ @document.new.active.should be_true
100
+ @document.new(:active => false).active.should be_false
101
+ end
102
+
103
+ context "root document" do
104
+ should "have a nil _root_document" do
105
+ @document.new._root_document.should be_nil
106
+ end
107
+
108
+ should "set self to the root document on embedded documents" do
109
+ document = Class.new(RealPerson) do
110
+ many :pets
111
+ end
112
+
113
+ doc = document.new 'pets' => [{}]
114
+ doc.pets.first._root_document.should == doc
115
+ end
116
+ end
117
+
118
+ context "new?" do
119
+ should "be true if no id" do
120
+ @document.new.new?.should be_true
121
+ end
122
+
123
+ should "be true if id but using custom id and not saved yet" do
124
+ doc = @document.new
125
+ doc.id = '1234'
126
+ doc.new?.should be_true
127
+ end
128
+ end
129
+
130
+ context "clone" do
131
+ should "not set the id" do
132
+ doc = @document.create(:name => "foo", :age => 27)
133
+ clone = doc.clone
134
+ clone.should be_new
135
+ end
136
+
137
+ should "copy the attributes" do
138
+ doc = @document.create(:name => "foo", :age => 27)
139
+ clone = doc.clone
140
+ clone.name.should == "foo"
141
+ clone.age.should == 27
142
+ end
143
+ end
144
+
145
+
146
+ context "equality" do
147
+ should "be equal if id and class are the same" do
148
+ (@document.new('_id' => 1) == @document.new('_id' => 1)).should be(true)
149
+ end
150
+
151
+ should "not be equal if class same but id different" do
152
+ (@document.new('_id' => 1) == @document.new('_id' => 2)).should be(false)
153
+ end
154
+
155
+ should "not be equal if id same but class different" do
156
+ @another_document = Class.new do
157
+ include MongoMapper::Document
158
+ set_collection_name 'test'
159
+ end
160
+
161
+ (@document.new('_id' => 1) == @another_document.new('_id' => 1)).should be(false)
162
+ end
163
+ end
164
+ end # instance of a document
165
+ end # DocumentTest
@@ -0,0 +1,125 @@
1
+ require 'test_helper'
2
+
3
+ class DynamicFinderTest < Test::Unit::TestCase
4
+ include MongoMapper
5
+
6
+ should "initialize with method" do
7
+ finder = DynamicFinder.new(:foobar)
8
+ finder.method.should == :foobar
9
+ end
10
+
11
+ context "found?" do
12
+ should "be true for find_by" do
13
+ DynamicFinder.new(:find_by_foo).found?.should be_true
14
+ end
15
+
16
+ should "be true for find_by with !" do
17
+ DynamicFinder.new(:find_by_foo!).found?.should be_true
18
+ end
19
+
20
+ should "be true for find_all_by" do
21
+ DynamicFinder.new(:find_all_by_foo).found?.should be_true
22
+ end
23
+
24
+ should "be true for find_or_initialize_by" do
25
+ DynamicFinder.new(:find_or_initialize_by_foo).found?.should be_true
26
+ end
27
+
28
+ should "be true for find_or_create_by" do
29
+ DynamicFinder.new(:find_or_create_by_foo).found?.should be_true
30
+ end
31
+
32
+ should "be false for anything else" do
33
+ [:foobar, :bazwick].each do |method|
34
+ DynamicFinder.new(method).found?.should be_false
35
+ end
36
+ end
37
+ end
38
+
39
+ context "find_all_by" do
40
+ should "parse one attribute" do
41
+ DynamicFinder.new(:find_all_by_foo).attributes.should == %w(foo)
42
+ end
43
+
44
+ should "parse multiple attributes" do
45
+ DynamicFinder.new(:find_all_by_foo_and_bar).attributes.should == %w(foo bar)
46
+ DynamicFinder.new(:find_all_by_foo_and_bar_and_baz).attributes.should == %w(foo bar baz)
47
+ end
48
+
49
+ should "set finder to :all" do
50
+ DynamicFinder.new(:find_all_by_foo_and_bar).finder.should == :all
51
+ end
52
+ end
53
+
54
+ context "find_by" do
55
+ should "parse one attribute" do
56
+ DynamicFinder.new(:find_by_foo).attributes.should == %w(foo)
57
+ end
58
+
59
+ should "parse multiple attributes" do
60
+ DynamicFinder.new(:find_by_foo_and_bar).attributes.should == %w(foo bar)
61
+ end
62
+
63
+ should "set finder to :first" do
64
+ DynamicFinder.new(:find_by_foo).finder.should == :first
65
+ end
66
+
67
+ should "set bang to false" do
68
+ DynamicFinder.new(:find_by_foo).bang.should be_false
69
+ end
70
+ end
71
+
72
+ context "find_by with !" do
73
+ should "parse one attribute" do
74
+ DynamicFinder.new(:find_by_foo!).attributes.should == %w(foo)
75
+ end
76
+
77
+ should "parse multiple attributes" do
78
+ DynamicFinder.new(:find_by_foo_and_bar!).attributes.should == %w(foo bar)
79
+ end
80
+
81
+ should "set finder to :first" do
82
+ DynamicFinder.new(:find_by_foo!).finder.should == :first
83
+ end
84
+
85
+ should "set bang to true" do
86
+ DynamicFinder.new(:find_by_foo!).bang.should be_true
87
+ end
88
+ end
89
+
90
+ context "find_or_initialize_by" do
91
+ should "parse one attribute" do
92
+ DynamicFinder.new(:find_or_initialize_by_foo).attributes.should == %w(foo)
93
+ end
94
+
95
+ should "parse multiple attributes" do
96
+ DynamicFinder.new(:find_or_initialize_by_foo_and_bar).attributes.should == %w(foo bar)
97
+ end
98
+
99
+ should "set finder to :first" do
100
+ DynamicFinder.new(:find_or_initialize_by_foo).finder.should == :first
101
+ end
102
+
103
+ should "set instantiator to new" do
104
+ DynamicFinder.new(:find_or_initialize_by_foo).instantiator.should == :new
105
+ end
106
+ end
107
+
108
+ context "find_or_create_by" do
109
+ should "parse one attribute" do
110
+ DynamicFinder.new(:find_or_create_by_foo).attributes.should == %w(foo)
111
+ end
112
+
113
+ should "parse multiple attributes" do
114
+ DynamicFinder.new(:find_or_create_by_foo_and_bar).attributes.should == %w(foo bar)
115
+ end
116
+
117
+ should "set finder to :first" do
118
+ DynamicFinder.new(:find_or_create_by_foo).finder.should == :first
119
+ end
120
+
121
+ should "set instantiator to new" do
122
+ DynamicFinder.new(:find_or_create_by_foo).instantiator.should == :create
123
+ end
124
+ end
125
+ end