viking-sequel 3.10.0

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 (237) hide show
  1. data/CHANGELOG +3134 -0
  2. data/COPYING +19 -0
  3. data/README.rdoc +723 -0
  4. data/Rakefile +193 -0
  5. data/bin/sequel +196 -0
  6. data/doc/advanced_associations.rdoc +644 -0
  7. data/doc/cheat_sheet.rdoc +218 -0
  8. data/doc/dataset_basics.rdoc +106 -0
  9. data/doc/dataset_filtering.rdoc +158 -0
  10. data/doc/opening_databases.rdoc +296 -0
  11. data/doc/prepared_statements.rdoc +104 -0
  12. data/doc/reflection.rdoc +84 -0
  13. data/doc/release_notes/1.0.txt +38 -0
  14. data/doc/release_notes/1.1.txt +143 -0
  15. data/doc/release_notes/1.3.txt +101 -0
  16. data/doc/release_notes/1.4.0.txt +53 -0
  17. data/doc/release_notes/1.5.0.txt +155 -0
  18. data/doc/release_notes/2.0.0.txt +298 -0
  19. data/doc/release_notes/2.1.0.txt +271 -0
  20. data/doc/release_notes/2.10.0.txt +328 -0
  21. data/doc/release_notes/2.11.0.txt +215 -0
  22. data/doc/release_notes/2.12.0.txt +534 -0
  23. data/doc/release_notes/2.2.0.txt +253 -0
  24. data/doc/release_notes/2.3.0.txt +88 -0
  25. data/doc/release_notes/2.4.0.txt +106 -0
  26. data/doc/release_notes/2.5.0.txt +137 -0
  27. data/doc/release_notes/2.6.0.txt +157 -0
  28. data/doc/release_notes/2.7.0.txt +166 -0
  29. data/doc/release_notes/2.8.0.txt +171 -0
  30. data/doc/release_notes/2.9.0.txt +97 -0
  31. data/doc/release_notes/3.0.0.txt +221 -0
  32. data/doc/release_notes/3.1.0.txt +406 -0
  33. data/doc/release_notes/3.10.0.txt +286 -0
  34. data/doc/release_notes/3.2.0.txt +268 -0
  35. data/doc/release_notes/3.3.0.txt +192 -0
  36. data/doc/release_notes/3.4.0.txt +325 -0
  37. data/doc/release_notes/3.5.0.txt +510 -0
  38. data/doc/release_notes/3.6.0.txt +366 -0
  39. data/doc/release_notes/3.7.0.txt +179 -0
  40. data/doc/release_notes/3.8.0.txt +151 -0
  41. data/doc/release_notes/3.9.0.txt +233 -0
  42. data/doc/schema.rdoc +36 -0
  43. data/doc/sharding.rdoc +113 -0
  44. data/doc/virtual_rows.rdoc +205 -0
  45. data/lib/sequel.rb +1 -0
  46. data/lib/sequel/adapters/ado.rb +90 -0
  47. data/lib/sequel/adapters/ado/mssql.rb +30 -0
  48. data/lib/sequel/adapters/amalgalite.rb +176 -0
  49. data/lib/sequel/adapters/db2.rb +139 -0
  50. data/lib/sequel/adapters/dbi.rb +113 -0
  51. data/lib/sequel/adapters/do.rb +188 -0
  52. data/lib/sequel/adapters/do/mysql.rb +49 -0
  53. data/lib/sequel/adapters/do/postgres.rb +91 -0
  54. data/lib/sequel/adapters/do/sqlite.rb +40 -0
  55. data/lib/sequel/adapters/firebird.rb +283 -0
  56. data/lib/sequel/adapters/informix.rb +77 -0
  57. data/lib/sequel/adapters/jdbc.rb +587 -0
  58. data/lib/sequel/adapters/jdbc/as400.rb +58 -0
  59. data/lib/sequel/adapters/jdbc/h2.rb +133 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
  61. data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
  62. data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
  64. data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
  65. data/lib/sequel/adapters/mysql.rb +421 -0
  66. data/lib/sequel/adapters/odbc.rb +143 -0
  67. data/lib/sequel/adapters/odbc/mssql.rb +42 -0
  68. data/lib/sequel/adapters/openbase.rb +64 -0
  69. data/lib/sequel/adapters/oracle.rb +131 -0
  70. data/lib/sequel/adapters/postgres.rb +504 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +490 -0
  72. data/lib/sequel/adapters/shared/mysql.rb +498 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +195 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +830 -0
  75. data/lib/sequel/adapters/shared/progress.rb +44 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +389 -0
  77. data/lib/sequel/adapters/sqlite.rb +224 -0
  78. data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
  79. data/lib/sequel/connection_pool.rb +99 -0
  80. data/lib/sequel/connection_pool/sharded_single.rb +84 -0
  81. data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
  82. data/lib/sequel/connection_pool/single.rb +29 -0
  83. data/lib/sequel/connection_pool/threaded.rb +150 -0
  84. data/lib/sequel/core.rb +293 -0
  85. data/lib/sequel/core_sql.rb +241 -0
  86. data/lib/sequel/database.rb +1079 -0
  87. data/lib/sequel/database/schema_generator.rb +327 -0
  88. data/lib/sequel/database/schema_methods.rb +203 -0
  89. data/lib/sequel/database/schema_sql.rb +320 -0
  90. data/lib/sequel/dataset.rb +32 -0
  91. data/lib/sequel/dataset/actions.rb +441 -0
  92. data/lib/sequel/dataset/features.rb +86 -0
  93. data/lib/sequel/dataset/graph.rb +254 -0
  94. data/lib/sequel/dataset/misc.rb +119 -0
  95. data/lib/sequel/dataset/mutation.rb +64 -0
  96. data/lib/sequel/dataset/prepared_statements.rb +227 -0
  97. data/lib/sequel/dataset/query.rb +709 -0
  98. data/lib/sequel/dataset/sql.rb +996 -0
  99. data/lib/sequel/exceptions.rb +51 -0
  100. data/lib/sequel/extensions/blank.rb +43 -0
  101. data/lib/sequel/extensions/inflector.rb +242 -0
  102. data/lib/sequel/extensions/looser_typecasting.rb +21 -0
  103. data/lib/sequel/extensions/migration.rb +239 -0
  104. data/lib/sequel/extensions/named_timezones.rb +61 -0
  105. data/lib/sequel/extensions/pagination.rb +100 -0
  106. data/lib/sequel/extensions/pretty_table.rb +82 -0
  107. data/lib/sequel/extensions/query.rb +52 -0
  108. data/lib/sequel/extensions/schema_dumper.rb +271 -0
  109. data/lib/sequel/extensions/sql_expr.rb +122 -0
  110. data/lib/sequel/extensions/string_date_time.rb +46 -0
  111. data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
  112. data/lib/sequel/metaprogramming.rb +9 -0
  113. data/lib/sequel/model.rb +120 -0
  114. data/lib/sequel/model/associations.rb +1514 -0
  115. data/lib/sequel/model/base.rb +1069 -0
  116. data/lib/sequel/model/default_inflections.rb +45 -0
  117. data/lib/sequel/model/errors.rb +39 -0
  118. data/lib/sequel/model/exceptions.rb +21 -0
  119. data/lib/sequel/model/inflections.rb +162 -0
  120. data/lib/sequel/model/plugins.rb +70 -0
  121. data/lib/sequel/plugins/active_model.rb +59 -0
  122. data/lib/sequel/plugins/association_dependencies.rb +103 -0
  123. data/lib/sequel/plugins/association_proxies.rb +41 -0
  124. data/lib/sequel/plugins/boolean_readers.rb +53 -0
  125. data/lib/sequel/plugins/caching.rb +141 -0
  126. data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
  127. data/lib/sequel/plugins/composition.rb +138 -0
  128. data/lib/sequel/plugins/force_encoding.rb +72 -0
  129. data/lib/sequel/plugins/hook_class_methods.rb +126 -0
  130. data/lib/sequel/plugins/identity_map.rb +116 -0
  131. data/lib/sequel/plugins/instance_filters.rb +98 -0
  132. data/lib/sequel/plugins/instance_hooks.rb +57 -0
  133. data/lib/sequel/plugins/lazy_attributes.rb +77 -0
  134. data/lib/sequel/plugins/many_through_many.rb +208 -0
  135. data/lib/sequel/plugins/nested_attributes.rb +206 -0
  136. data/lib/sequel/plugins/optimistic_locking.rb +81 -0
  137. data/lib/sequel/plugins/rcte_tree.rb +281 -0
  138. data/lib/sequel/plugins/schema.rb +66 -0
  139. data/lib/sequel/plugins/serialization.rb +166 -0
  140. data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
  141. data/lib/sequel/plugins/subclasses.rb +45 -0
  142. data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
  143. data/lib/sequel/plugins/timestamps.rb +87 -0
  144. data/lib/sequel/plugins/touch.rb +118 -0
  145. data/lib/sequel/plugins/typecast_on_load.rb +72 -0
  146. data/lib/sequel/plugins/validation_class_methods.rb +405 -0
  147. data/lib/sequel/plugins/validation_helpers.rb +223 -0
  148. data/lib/sequel/sql.rb +1020 -0
  149. data/lib/sequel/timezones.rb +161 -0
  150. data/lib/sequel/version.rb +12 -0
  151. data/lib/sequel_core.rb +1 -0
  152. data/lib/sequel_model.rb +1 -0
  153. data/spec/adapters/firebird_spec.rb +407 -0
  154. data/spec/adapters/informix_spec.rb +97 -0
  155. data/spec/adapters/mssql_spec.rb +403 -0
  156. data/spec/adapters/mysql_spec.rb +1019 -0
  157. data/spec/adapters/oracle_spec.rb +286 -0
  158. data/spec/adapters/postgres_spec.rb +969 -0
  159. data/spec/adapters/spec_helper.rb +51 -0
  160. data/spec/adapters/sqlite_spec.rb +432 -0
  161. data/spec/core/connection_pool_spec.rb +808 -0
  162. data/spec/core/core_sql_spec.rb +417 -0
  163. data/spec/core/database_spec.rb +1662 -0
  164. data/spec/core/dataset_spec.rb +3827 -0
  165. data/spec/core/expression_filters_spec.rb +595 -0
  166. data/spec/core/object_graph_spec.rb +296 -0
  167. data/spec/core/schema_generator_spec.rb +159 -0
  168. data/spec/core/schema_spec.rb +830 -0
  169. data/spec/core/spec_helper.rb +56 -0
  170. data/spec/core/version_spec.rb +7 -0
  171. data/spec/extensions/active_model_spec.rb +76 -0
  172. data/spec/extensions/association_dependencies_spec.rb +127 -0
  173. data/spec/extensions/association_proxies_spec.rb +50 -0
  174. data/spec/extensions/blank_spec.rb +67 -0
  175. data/spec/extensions/boolean_readers_spec.rb +92 -0
  176. data/spec/extensions/caching_spec.rb +250 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +252 -0
  178. data/spec/extensions/composition_spec.rb +194 -0
  179. data/spec/extensions/force_encoding_spec.rb +117 -0
  180. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  181. data/spec/extensions/identity_map_spec.rb +202 -0
  182. data/spec/extensions/inflector_spec.rb +181 -0
  183. data/spec/extensions/instance_filters_spec.rb +55 -0
  184. data/spec/extensions/instance_hooks_spec.rb +133 -0
  185. data/spec/extensions/lazy_attributes_spec.rb +153 -0
  186. data/spec/extensions/looser_typecasting_spec.rb +39 -0
  187. data/spec/extensions/many_through_many_spec.rb +884 -0
  188. data/spec/extensions/migration_spec.rb +332 -0
  189. data/spec/extensions/named_timezones_spec.rb +72 -0
  190. data/spec/extensions/nested_attributes_spec.rb +396 -0
  191. data/spec/extensions/optimistic_locking_spec.rb +100 -0
  192. data/spec/extensions/pagination_spec.rb +99 -0
  193. data/spec/extensions/pretty_table_spec.rb +91 -0
  194. data/spec/extensions/query_spec.rb +85 -0
  195. data/spec/extensions/rcte_tree_spec.rb +205 -0
  196. data/spec/extensions/schema_dumper_spec.rb +357 -0
  197. data/spec/extensions/schema_spec.rb +127 -0
  198. data/spec/extensions/serialization_spec.rb +209 -0
  199. data/spec/extensions/single_table_inheritance_spec.rb +96 -0
  200. data/spec/extensions/spec_helper.rb +91 -0
  201. data/spec/extensions/sql_expr_spec.rb +89 -0
  202. data/spec/extensions/string_date_time_spec.rb +93 -0
  203. data/spec/extensions/subclasses_spec.rb +52 -0
  204. data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
  205. data/spec/extensions/thread_local_timezones_spec.rb +45 -0
  206. data/spec/extensions/timestamps_spec.rb +150 -0
  207. data/spec/extensions/touch_spec.rb +155 -0
  208. data/spec/extensions/typecast_on_load_spec.rb +69 -0
  209. data/spec/extensions/validation_class_methods_spec.rb +984 -0
  210. data/spec/extensions/validation_helpers_spec.rb +438 -0
  211. data/spec/integration/associations_test.rb +281 -0
  212. data/spec/integration/database_test.rb +26 -0
  213. data/spec/integration/dataset_test.rb +963 -0
  214. data/spec/integration/eager_loader_test.rb +734 -0
  215. data/spec/integration/model_test.rb +130 -0
  216. data/spec/integration/plugin_test.rb +814 -0
  217. data/spec/integration/prepared_statement_test.rb +213 -0
  218. data/spec/integration/schema_test.rb +361 -0
  219. data/spec/integration/spec_helper.rb +73 -0
  220. data/spec/integration/timezone_test.rb +55 -0
  221. data/spec/integration/transaction_test.rb +122 -0
  222. data/spec/integration/type_test.rb +96 -0
  223. data/spec/model/association_reflection_spec.rb +175 -0
  224. data/spec/model/associations_spec.rb +2633 -0
  225. data/spec/model/base_spec.rb +418 -0
  226. data/spec/model/dataset_methods_spec.rb +78 -0
  227. data/spec/model/eager_loading_spec.rb +1391 -0
  228. data/spec/model/hooks_spec.rb +240 -0
  229. data/spec/model/inflector_spec.rb +26 -0
  230. data/spec/model/model_spec.rb +593 -0
  231. data/spec/model/plugins_spec.rb +236 -0
  232. data/spec/model/record_spec.rb +1500 -0
  233. data/spec/model/spec_helper.rb +97 -0
  234. data/spec/model/validations_spec.rb +153 -0
  235. data/spec/rcov.opts +6 -0
  236. data/spec/spec_config.rb.example +10 -0
  237. metadata +346 -0
@@ -0,0 +1,202 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::IdentityMap" do
4
+ before do
5
+ class ::IdentityMapModel < Sequel::Model
6
+ plugin :identity_map
7
+ attr_accessor :foo
8
+ columns :id
9
+ ds = dataset
10
+ def ds.fetch_rows(sql)
11
+ c = @opts[:where].args.first
12
+ c = c.column if c.is_a?(Sequel::SQL::QualifiedIdentifier)
13
+ h = {c=>@opts[:where].args.last}
14
+ execute(sql)
15
+ yield h
16
+ end
17
+ end
18
+ class ::IdentityMapAlbum < ::IdentityMapModel
19
+ columns :id, :artist_id
20
+ end
21
+ class ::IdentityMapArtist < ::IdentityMapModel
22
+ end
23
+ @c = ::IdentityMapModel
24
+ @c1 = ::IdentityMapAlbum
25
+ @c2 = ::IdentityMapArtist
26
+ MODEL_DB.reset
27
+ end
28
+ after do
29
+ Object.send(:remove_const, :IdentityMapAlbum)
30
+ Object.send(:remove_const, :IdentityMapArtist)
31
+ Object.send(:remove_const, :IdentityMapModel)
32
+ end
33
+
34
+ it "#identity_map should return a hash if an identity map is currently being used" do
35
+ @c.with_identity_map{@c.identity_map.should == {}}
36
+ end
37
+
38
+ it "#identity_map should return nil if an identity map is not currently being used" do
39
+ @c.identity_map.should == nil
40
+ end
41
+
42
+ it "#identity_map_key should be the same for the same class and pk" do
43
+ @c.identity_map_key(1).should == @c.identity_map_key(1)
44
+ end
45
+
46
+ it "#identity_map_key should be different for a different class" do
47
+ @c1.identity_map_key(1).should_not == @c2.identity_map_key(1)
48
+ end
49
+
50
+ it "#identity_map_key should be different for different anonymous classes" do
51
+ Class.new(@c).identity_map_key(1).should_not == Class.new(@c).identity_map_key(1)
52
+ end
53
+
54
+ it "#identity_map_key should be different for a different pk" do
55
+ @c.identity_map_key(1).should_not == @c.identity_map_key(2)
56
+ end
57
+
58
+ it "#identity_map_key should be different if the pk is nil" do
59
+ @c.identity_map_key(nil).should_not == @c.identity_map_key(nil)
60
+ end
61
+
62
+ it "#load should return an object if there is no current identity map" do
63
+ o = @c.load(:id=>1)
64
+ o.should be_a_kind_of(@c)
65
+ o.values.should == {:id=>1}
66
+ end
67
+
68
+ it "#load should return an object if there is a current identity map" do
69
+ @c.with_identity_map do
70
+ o = @c.load(:id=>1)
71
+ o.should be_a_kind_of(@c)
72
+ o.values.should == {:id=>1}
73
+ end
74
+ end
75
+
76
+ it "#load should should store the object in the current identity map if it isn't already there" do
77
+ @c.with_identity_map do
78
+ @c.identity_map[@c.identity_map_key(1)].should == nil
79
+ o = @c.load(:id=>1)
80
+ @c.identity_map[@c.identity_map_key(1)].should == o
81
+ end
82
+ end
83
+
84
+ it "#load should update the record in the current identity map if new fields if it is already there" do
85
+ @c.with_identity_map do
86
+ o = @c.load(:id=>1, :a=>2)
87
+ o.values.should == {:id=>1, :a=>2}
88
+ o = @c.load(:id=>1, :b=>3)
89
+ o.values.should == {:id=>1, :a=>2, :b=>3}
90
+ end
91
+ end
92
+
93
+ it "#load should not update existing fields in the record if the record is in the current identity map" do
94
+ @c.with_identity_map do
95
+ o = @c.load(:id=>1, :a=>2)
96
+ o.values.should == {:id=>1, :a=>2}
97
+ o = @c.load(:id=>1, :a=>4)
98
+ o.values.should == {:id=>1, :a=>2}
99
+ end
100
+ end
101
+
102
+ it "should use the identity map as a lookup cache in Model.[] to save on database queries" do
103
+ @c.with_identity_map do
104
+ MODEL_DB.sqls.length.should == 0
105
+ o = @c[1]
106
+ MODEL_DB.sqls.length.should == 1
107
+ o.foo = 1
108
+ @c[1].foo.should == o.foo
109
+ MODEL_DB.sqls.length.should == 1
110
+ @c[2].foo.should_not == o.foo
111
+ MODEL_DB.sqls.length.should == 2
112
+ end
113
+ end
114
+
115
+ it "should remove instances from the identity map if they are deleted or destroyed" do
116
+ @c.with_identity_map do
117
+ MODEL_DB.sqls.length.should == 0
118
+ o = @c[1]
119
+ MODEL_DB.sqls.length.should == 1
120
+ o.foo = 1
121
+ @c[1].should == o
122
+ MODEL_DB.sqls.length.should == 1
123
+ o.destroy
124
+ MODEL_DB.sqls.length.should == 2
125
+ @c[1].foo.should_not == o.foo
126
+ MODEL_DB.sqls.length.should == 3
127
+
128
+ MODEL_DB.reset
129
+ o = @c[2]
130
+ MODEL_DB.sqls.length.should == 1
131
+ o.foo = 1
132
+ @c[2].should == o
133
+ MODEL_DB.sqls.length.should == 1
134
+ o.delete
135
+ MODEL_DB.sqls.length.should == 2
136
+ @c[2].foo.should_not == o.foo
137
+ MODEL_DB.sqls.length.should == 3
138
+ end
139
+ end
140
+
141
+ it "should use the identity map as a lookup cache when retrieving many_to_one associated records" do
142
+ @c1.many_to_one :artist, :class=>@c2
143
+ @c.with_identity_map do
144
+ MODEL_DB.sqls.length.should == 0
145
+ o = @c1.load(:id=>1, :artist_id=>2)
146
+ a = o.artist
147
+ a.should be_a_kind_of(@c2)
148
+ MODEL_DB.sqls.length.should == 1
149
+ o = @c1.load(:id=>2, :artist_id=>2)
150
+ o.artist.should == a
151
+ MODEL_DB.sqls.length.should == 1
152
+ o = @c1.load(:id=>3, :artist_id=>3)
153
+ o.artist.should_not == a
154
+ MODEL_DB.sqls.length.should == 2
155
+ end
156
+ end
157
+
158
+ it "should not use the identity map as a lookup cache for a one_to_one association" do
159
+ c = @c2
160
+ @c2.one_to_one :artist, :class=>@c1, :key=>:artist_id
161
+ @c.with_identity_map do
162
+ MODEL_DB.sqls.length.should == 0
163
+ o = @c2.load(:id=>2)
164
+ a = o.artist
165
+ a.should be_a_kind_of(@c1)
166
+ MODEL_DB.sqls.length.should == 1
167
+ o.reload
168
+ MODEL_DB.sqls.length.should == 2
169
+ o.artist.should == a
170
+ MODEL_DB.sqls.length.should == 3
171
+ end
172
+ end
173
+
174
+ it "should not use the identity map as a lookup cache if the assocation has a nil :key option" do
175
+ c = @c2
176
+ @c1.many_to_one :artist, :class=>@c2, :key=>nil, :dataset=>proc{c.filter(:artist_id=>artist_id)}
177
+ @c.with_identity_map do
178
+ MODEL_DB.sqls.length.should == 0
179
+ o = @c1.load(:id=>1, :artist_id=>2)
180
+ a = o.artist
181
+ a.should be_a_kind_of(@c2)
182
+ MODEL_DB.sqls.length.should == 1
183
+ o = @c1.load(:id=>2, :artist_id=>2)
184
+ o.artist.should == a
185
+ MODEL_DB.sqls.length.should == 2
186
+ end
187
+ end
188
+
189
+ it "should not use the identity map as a lookup cache if the assocation's :primary_key option doesn't match the primary key of the associated class" do
190
+ @c1.many_to_one :artist, :class=>@c2, :primary_key=>:artist_id
191
+ @c.with_identity_map do
192
+ MODEL_DB.sqls.length.should == 0
193
+ o = @c1.load(:id=>1, :artist_id=>2)
194
+ a = o.artist
195
+ a.should be_a_kind_of(@c2)
196
+ MODEL_DB.sqls.length.should == 1
197
+ o = @c1.load(:id=>2, :artist_id=>2)
198
+ o.artist.should == a
199
+ MODEL_DB.sqls.length.should == 2
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,181 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe String do
4
+ it "#camelize and #camelcase should transform the word to CamelCase" do
5
+ "egg_and_hams".camelize.should == "EggAndHams"
6
+ "egg_and_hams".camelize(false).should == "eggAndHams"
7
+ "post".camelize.should == "Post"
8
+ "post".camelcase.should == "Post"
9
+ end
10
+
11
+ it "#constantize should eval the string to get a constant" do
12
+ "String".constantize.should == String
13
+ "String::Inflections".constantize.should == String::Inflections
14
+ proc{"BKSDDF".constantize}.should raise_error
15
+ proc{"++A++".constantize}.should raise_error
16
+ end
17
+
18
+ it "#dasherize should transform underscores to dashes" do
19
+ "egg_and_hams".dasherize.should == "egg-and-hams"
20
+ "post".dasherize.should == "post"
21
+ end
22
+
23
+ it "#demodulize should remove any preceding modules" do
24
+ "String::Inflections::Blah".demodulize.should == "Blah"
25
+ "String::Inflections".demodulize.should == "Inflections"
26
+ "String".demodulize.should == "String"
27
+ end
28
+
29
+ it "#humanize should remove _i, transform underscore to spaces, and capitalize" do
30
+ "egg_and_hams".humanize.should == "Egg and hams"
31
+ "post".humanize.should == "Post"
32
+ "post_id".humanize.should == "Post"
33
+ end
34
+
35
+ it "#titleize and #titlecase should underscore, humanize, and capitalize all words" do
36
+ "egg-and: hams".titleize.should == "Egg And: Hams"
37
+ "post".titleize.should == "Post"
38
+ "post".titlecase.should == "Post"
39
+ end
40
+
41
+ it "#underscore should add underscores between CamelCased words, change :: to / and - to _, and downcase" do
42
+ "EggAndHams".underscore.should == "egg_and_hams"
43
+ "EGGAndHams".underscore.should == "egg_and_hams"
44
+ "Egg::And::Hams".underscore.should == "egg/and/hams"
45
+ "post".underscore.should == "post"
46
+ "post-id".underscore.should == "post_id"
47
+ end
48
+
49
+ it "#pluralize should transform words from singular to plural" do
50
+ "post".pluralize.should == "posts"
51
+ "octopus".pluralize.should =="octopuses"
52
+ "the blue mailman".pluralize.should == "the blue mailmen"
53
+ "CamelOctopus".pluralize.should == "CamelOctopuses"
54
+ end
55
+
56
+ it "#singularize should transform words from plural to singular" do
57
+ "posts".singularize.should == "post"
58
+ "octopuses".singularize.should == "octopus"
59
+ "the blue mailmen".singularize.should == "the blue mailman"
60
+ "CamelOctopuses".singularize.should == "CamelOctopus"
61
+ end
62
+
63
+ it "#tableize should transform class names to table names" do
64
+ "RawScaledScorer".tableize.should == "raw_scaled_scorers"
65
+ "egg_and_ham".tableize.should == "egg_and_hams"
66
+ "fancyCategory".tableize.should == "fancy_categories"
67
+ end
68
+
69
+ it "#classify should tranform table names to class names" do
70
+ "egg_and_hams".classify.should == "EggAndHam"
71
+ "post".classify.should == "Post"
72
+ end
73
+
74
+ it "#foreign_key should create a foreign key name from a class name" do
75
+ "Message".foreign_key.should == "message_id"
76
+ "Message".foreign_key(false).should == "messageid"
77
+ "Admin::Post".foreign_key.should == "post_id"
78
+ end
79
+ end
80
+
81
+ describe String::Inflections do
82
+ before do
83
+ @plurals, @singulars, @uncountables = String.inflections.plurals.dup, String.inflections.singulars.dup, String.inflections.uncountables.dup
84
+ end
85
+ after do
86
+ String.inflections.plurals.replace(@plurals)
87
+ String.inflections.singulars.replace(@singulars)
88
+ String.inflections.uncountables.replace(@uncountables)
89
+ end
90
+
91
+ it "should be possible to clear the list of singulars, plurals, and uncountables" do
92
+ String.inflections.clear(:plurals)
93
+ String.inflections.plurals.should == []
94
+ String.inflections.plural('blah', 'blahs')
95
+ String.inflections.clear
96
+ String.inflections.plurals.should == []
97
+ String.inflections.singulars.should == []
98
+ String.inflections.uncountables.should == []
99
+ end
100
+
101
+ it "should be able to specify new inflection rules" do
102
+ String.inflections do |i|
103
+ i.plural(/xx$/i, 'xxx')
104
+ i.singular(/ttt$/i, 'tt')
105
+ i.irregular('yy', 'yyy')
106
+ i.uncountable(%w'zz')
107
+ end
108
+ 'roxx'.pluralize.should == 'roxxx'
109
+ 'rottt'.singularize.should == 'rott'
110
+ 'yy'.pluralize.should == 'yyy'
111
+ 'yyy'.singularize.should == 'yy'
112
+ 'zz'.pluralize.should == 'zz'
113
+ 'zz'.singularize.should == 'zz'
114
+ end
115
+
116
+ it "should be yielded and returned by String.inflections" do
117
+ String.inflections{|i| i.should == String::Inflections}.should == String::Inflections
118
+ end
119
+ end
120
+
121
+ describe 'Default inflections' do
122
+ it "should support the default inflection rules" do
123
+ {
124
+ :test=>:tests,
125
+ :ax=>:axes,
126
+ :testis=>:testes,
127
+ :octopus=>:octopuses,
128
+ :virus=>:viruses,
129
+ :alias=>:aliases,
130
+ :status=>:statuses,
131
+ :bus=>:buses,
132
+ :buffalo=>:buffaloes,
133
+ :tomato=>:tomatoes,
134
+ :datum=>:data,
135
+ :bacterium=>:bacteria,
136
+ :analysis=>:analyses,
137
+ :basis=>:bases,
138
+ :diagnosis=>:diagnoses,
139
+ :parenthesis=>:parentheses,
140
+ :prognosis=>:prognoses,
141
+ :synopsis=>:synopses,
142
+ :thesis=>:theses,
143
+ :wife=>:wives,
144
+ :giraffe=>:giraffes,
145
+ :self=>:selves,
146
+ :dwarf=>:dwarves,
147
+ :hive=>:hives,
148
+ :fly=>:flies,
149
+ :buy=>:buys,
150
+ :soliloquy=>:soliloquies,
151
+ :day=>:days,
152
+ :attorney=>:attorneys,
153
+ :boy=>:boys,
154
+ :hoax=>:hoaxes,
155
+ :lunch=>:lunches,
156
+ :princess=>:princesses,
157
+ :matrix=>:matrices,
158
+ :vertex=>:vertices,
159
+ :index=>:indices,
160
+ :mouse=>:mice,
161
+ :louse=>:lice,
162
+ :quiz=>:quizzes,
163
+ :motive=>:motives,
164
+ :movie=>:movies,
165
+ :series=>:series,
166
+ :crisis=>:crises,
167
+ :person=>:people,
168
+ :man=>:men,
169
+ :woman=>:women,
170
+ :child=>:children,
171
+ :sex=>:sexes,
172
+ :move=>:moves
173
+ }.each do |k, v|
174
+ k.to_s.pluralize.should == v.to_s
175
+ v.to_s.singularize.should == k.to_s
176
+ end
177
+ [:equipment, :information, :rice, :money, :species, :series, :fish, :sheep, :news].each do |a|
178
+ a.to_s.pluralize.should == a.to_s.singularize
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,55 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "instance_filters plugin" do
4
+ before do
5
+ @c = Class.new(Sequel::Model(:people)) do
6
+ end
7
+ @sql = sql = ''
8
+ @v = v = [1]
9
+ @c.dataset.quote_identifiers = false
10
+ @c.dataset.meta_def(:update) do |opts|
11
+ sql.replace(update_sql(opts))
12
+ return v.first
13
+ end
14
+ @c.dataset.meta_def(:delete) do
15
+ sql.replace(delete_sql)
16
+ return v.first
17
+ end
18
+ @c.columns :id, :name, :num
19
+ @c.plugin :instance_filters
20
+ @p = @c.load(:id=>1, :name=>'John', :num=>1)
21
+ end
22
+
23
+ specify "should raise an error when updating a stale record" do
24
+ @p.update(:name=>'Bob')
25
+ @sql.should == "UPDATE people SET name = 'Bob' WHERE (id = 1)"
26
+ @p.instance_filter(:name=>'Jim')
27
+ @v.replace([0])
28
+ proc{@p.update(:name=>'Joe')}.should raise_error(Sequel::Plugins::InstanceFilters::Error)
29
+ @sql.should == "UPDATE people SET name = 'Joe' WHERE ((id = 1) AND (name = 'Jim'))"
30
+ end
31
+
32
+ specify "should raise an error when destroying a stale record" do
33
+ @p.destroy
34
+ @sql.should == "DELETE FROM people WHERE (id = 1)"
35
+ @p.instance_filter(:name=>'Jim')
36
+ @v.replace([0])
37
+ proc{@p.destroy}.should raise_error(Sequel::Plugins::InstanceFilters::Error)
38
+ @sql.should == "DELETE FROM people WHERE ((id = 1) AND (name = 'Jim'))"
39
+ end
40
+
41
+ specify "should apply all instance filters" do
42
+ @p.instance_filter(:name=>'Jim')
43
+ @p.instance_filter{num > 2}
44
+ @p.update(:name=>'Bob')
45
+ @sql.should == "UPDATE people SET name = 'Bob' WHERE ((id = 1) AND (name = 'Jim') AND (num > 2))"
46
+ end
47
+
48
+ specify "should drop instance filters after updating" do
49
+ @p.instance_filter(:name=>'Joe')
50
+ @p.update(:name=>'Joe')
51
+ @sql.should == "UPDATE people SET name = 'Joe' WHERE ((id = 1) AND (name = 'Joe'))"
52
+ @p.update(:name=>'Bob')
53
+ @sql.should == "UPDATE people SET name = 'Bob' WHERE (id = 1)"
54
+ end
55
+ end
@@ -0,0 +1,133 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "InstanceHooks plugin" do
4
+ def r(x)
5
+ @r << x
6
+ x
7
+ end
8
+
9
+ before do
10
+ @c = Class.new(Sequel::Model(:items))
11
+ @c.plugin :instance_hooks
12
+ @c.raise_on_save_failure = false
13
+ @o = @c.new
14
+ @x = @c.load({:id=>1})
15
+ @r = []
16
+ end
17
+
18
+ it "should support before_create_hook and after_create_hook" do
19
+ @o.after_create_hook{r 1}
20
+ @o.before_create_hook{r 2}
21
+ @o.after_create_hook{r 3}
22
+ @o.before_create_hook{r 4}
23
+ @o.save.should_not == nil
24
+ @r.should == [4, 2, 1, 3]
25
+ end
26
+
27
+ it "should cancel the save if before_create_hook block returns false" do
28
+ @o.after_create_hook{r 1}
29
+ @o.before_create_hook{r false}
30
+ @o.before_create_hook{r 4}
31
+ @o.save.should == nil
32
+ @r.should == [4, false]
33
+ @r.clear
34
+ @o.save.should == nil
35
+ @r.should == [4, false]
36
+ end
37
+
38
+ it "should support before_update_hook and after_update_hook" do
39
+ @x.after_update_hook{r 1}
40
+ @x.before_update_hook{r 2}
41
+ @x.after_update_hook{r 3}
42
+ @x.before_update_hook{r 4}
43
+ @x.save.should_not == nil
44
+ @r.should == [4, 2, 1, 3]
45
+ @x.save.should_not == nil
46
+ @r.should == [4, 2, 1, 3]
47
+ end
48
+
49
+ it "should cancel the save if before_update_hook block returns false" do
50
+ @x.after_update_hook{r 1}
51
+ @x.before_update_hook{r false}
52
+ @x.before_update_hook{r 4}
53
+ @x.save.should == nil
54
+ @r.should == [4, false]
55
+ @r.clear
56
+ @x.save.should == nil
57
+ @r.should == [4, false]
58
+ end
59
+
60
+ it "should support before_save_hook and after_save_hook" do
61
+ @o.after_save_hook{r 1}
62
+ @o.before_save_hook{r 2}
63
+ @o.after_save_hook{r 3}
64
+ @o.before_save_hook{r 4}
65
+ @o.save.should_not == nil
66
+ @r.should == [4, 2, 1, 3]
67
+ @r.clear
68
+
69
+ @x.after_save_hook{r 1}
70
+ @x.before_save_hook{r 2}
71
+ @x.after_save_hook{r 3}
72
+ @x.before_save_hook{r 4}
73
+ @x.save.should_not == nil
74
+ @r.should == [4, 2, 1, 3]
75
+ @x.save.should_not == nil
76
+ @r.should == [4, 2, 1, 3]
77
+ end
78
+
79
+ it "should cancel the save if before_save_hook block returns false" do
80
+ @x.after_save_hook{r 1}
81
+ @x.before_save_hook{r false}
82
+ @x.before_save_hook{r 4}
83
+ @x.save.should == nil
84
+ @r.should == [4, false]
85
+ @r.clear
86
+
87
+ @x.after_save_hook{r 1}
88
+ @x.before_save_hook{r false}
89
+ @x.before_save_hook{r 4}
90
+ @x.save.should == nil
91
+ @r.should == [4, false]
92
+ @r.clear
93
+ @x.save.should == nil
94
+ @r.should == [4, false]
95
+ end
96
+
97
+ it "should support before_destroy_hook and after_destroy_hook" do
98
+ @x.after_destroy_hook{r 1}
99
+ @x.before_destroy_hook{r 2}
100
+ @x.after_destroy_hook{r 3}
101
+ @x.before_destroy_hook{r 4}
102
+ @x.destroy.should_not == nil
103
+ @r.should == [4, 2, 1, 3]
104
+ end
105
+
106
+ it "should cancel the destroy if before_destroy_hook block returns false" do
107
+ @x.after_destroy_hook{r 1}
108
+ @x.before_destroy_hook{r false}
109
+ @x.before_destroy_hook{r 4}
110
+ @x.destroy.should == nil
111
+ @r.should == [4, false]
112
+ end
113
+
114
+ it "should support before_validation_hook and after_validation_hook" do
115
+ @o.after_validation_hook{r 1}
116
+ @o.before_validation_hook{r 2}
117
+ @o.after_validation_hook{r 3}
118
+ @o.before_validation_hook{r 4}
119
+ @o.valid?.should == true
120
+ @r.should == [4, 2, 1, 3]
121
+ end
122
+
123
+ it "should cancel the save if before_validation_hook block returns false" do
124
+ @o.after_validation_hook{r 1}
125
+ @o.before_validation_hook{r false}
126
+ @o.before_validation_hook{r 4}
127
+ @o.valid?.should == false
128
+ @r.should == [4, false]
129
+ @r.clear
130
+ @o.valid?.should == false
131
+ @r.should == [4, false]
132
+ end
133
+ end