activerecord 2.3.18 → 3.2.22

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (454) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1014 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +222 -0
  5. data/examples/performance.rb +100 -126
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record/aggregations.rb +93 -99
  8. data/lib/active_record/associations/alias_tracker.rb +76 -0
  9. data/lib/active_record/associations/association.rb +247 -0
  10. data/lib/active_record/associations/association_scope.rb +134 -0
  11. data/lib/active_record/associations/belongs_to_association.rb +54 -61
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +17 -59
  13. data/lib/active_record/associations/builder/association.rb +55 -0
  14. data/lib/active_record/associations/builder/belongs_to.rb +88 -0
  15. data/lib/active_record/associations/builder/collection_association.rb +75 -0
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -0
  17. data/lib/active_record/associations/builder/has_many.rb +71 -0
  18. data/lib/active_record/associations/builder/has_one.rb +62 -0
  19. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  20. data/lib/active_record/associations/collection_association.rb +580 -0
  21. data/lib/active_record/associations/collection_proxy.rb +133 -0
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +39 -119
  23. data/lib/active_record/associations/has_many_association.rb +60 -79
  24. data/lib/active_record/associations/has_many_through_association.rb +127 -206
  25. data/lib/active_record/associations/has_one_association.rb +55 -114
  26. data/lib/active_record/associations/has_one_through_association.rb +25 -26
  27. data/lib/active_record/associations/join_dependency/join_association.rb +159 -0
  28. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  29. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  30. data/lib/active_record/associations/join_dependency.rb +214 -0
  31. data/lib/active_record/associations/join_helper.rb +55 -0
  32. data/lib/active_record/associations/preloader/association.rb +125 -0
  33. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  34. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  35. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  36. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  37. data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
  38. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  39. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  40. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  41. data/lib/active_record/associations/preloader/through_association.rb +67 -0
  42. data/lib/active_record/associations/preloader.rb +181 -0
  43. data/lib/active_record/associations/singular_association.rb +64 -0
  44. data/lib/active_record/associations/through_association.rb +87 -0
  45. data/lib/active_record/associations.rb +693 -1337
  46. data/lib/active_record/attribute_assignment.rb +221 -0
  47. data/lib/active_record/attribute_methods/before_type_cast.rb +31 -0
  48. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
  49. data/lib/active_record/attribute_methods/dirty.rb +111 -0
  50. data/lib/active_record/attribute_methods/primary_key.rb +114 -0
  51. data/lib/active_record/attribute_methods/query.rb +39 -0
  52. data/lib/active_record/attribute_methods/read.rb +136 -0
  53. data/lib/active_record/attribute_methods/serialization.rb +120 -0
  54. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
  55. data/lib/active_record/attribute_methods/write.rb +70 -0
  56. data/lib/active_record/attribute_methods.rb +211 -339
  57. data/lib/active_record/autosave_association.rb +179 -149
  58. data/lib/active_record/base.rb +401 -2907
  59. data/lib/active_record/callbacks.rb +91 -176
  60. data/lib/active_record/coders/yaml_column.rb +41 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +236 -119
  62. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +110 -58
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -74
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -35
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +71 -21
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +81 -311
  68. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +194 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +130 -83
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
  71. data/lib/active_record/connection_adapters/column.rb +296 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +280 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +272 -493
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +650 -405
  75. data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
  76. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +30 -9
  77. data/lib/active_record/connection_adapters/sqlite_adapter.rb +276 -147
  78. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  79. data/lib/active_record/counter_cache.rb +123 -0
  80. data/lib/active_record/dynamic_finder_match.rb +41 -14
  81. data/lib/active_record/dynamic_matchers.rb +84 -0
  82. data/lib/active_record/dynamic_scope_match.rb +13 -15
  83. data/lib/active_record/errors.rb +195 -0
  84. data/lib/active_record/explain.rb +86 -0
  85. data/lib/active_record/explain_subscriber.rb +25 -0
  86. data/lib/active_record/fixtures/file.rb +65 -0
  87. data/lib/active_record/fixtures.rb +695 -770
  88. data/lib/active_record/identity_map.rb +162 -0
  89. data/lib/active_record/inheritance.rb +174 -0
  90. data/lib/active_record/integration.rb +60 -0
  91. data/lib/active_record/locale/en.yml +9 -27
  92. data/lib/active_record/locking/optimistic.rb +76 -73
  93. data/lib/active_record/locking/pessimistic.rb +32 -10
  94. data/lib/active_record/log_subscriber.rb +72 -0
  95. data/lib/active_record/migration/command_recorder.rb +105 -0
  96. data/lib/active_record/migration.rb +415 -205
  97. data/lib/active_record/model_schema.rb +368 -0
  98. data/lib/active_record/nested_attributes.rb +153 -63
  99. data/lib/active_record/observer.rb +27 -103
  100. data/lib/active_record/persistence.rb +376 -0
  101. data/lib/active_record/query_cache.rb +49 -8
  102. data/lib/active_record/querying.rb +58 -0
  103. data/lib/active_record/railtie.rb +131 -0
  104. data/lib/active_record/railties/console_sandbox.rb +6 -0
  105. data/lib/active_record/railties/controller_runtime.rb +49 -0
  106. data/lib/active_record/railties/databases.rake +659 -0
  107. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  108. data/lib/active_record/readonly_attributes.rb +26 -0
  109. data/lib/active_record/reflection.rb +269 -120
  110. data/lib/active_record/relation/batches.rb +90 -0
  111. data/lib/active_record/relation/calculations.rb +372 -0
  112. data/lib/active_record/relation/delegation.rb +49 -0
  113. data/lib/active_record/relation/finder_methods.rb +402 -0
  114. data/lib/active_record/relation/predicate_builder.rb +63 -0
  115. data/lib/active_record/relation/query_methods.rb +417 -0
  116. data/lib/active_record/relation/spawn_methods.rb +180 -0
  117. data/lib/active_record/relation.rb +537 -0
  118. data/lib/active_record/result.rb +40 -0
  119. data/lib/active_record/sanitization.rb +194 -0
  120. data/lib/active_record/schema.rb +9 -6
  121. data/lib/active_record/schema_dumper.rb +55 -32
  122. data/lib/active_record/scoping/default.rb +142 -0
  123. data/lib/active_record/scoping/named.rb +200 -0
  124. data/lib/active_record/scoping.rb +152 -0
  125. data/lib/active_record/serialization.rb +8 -91
  126. data/lib/active_record/serializers/xml_serializer.rb +43 -197
  127. data/lib/active_record/session_store.rb +129 -103
  128. data/lib/active_record/store.rb +52 -0
  129. data/lib/active_record/test_case.rb +30 -23
  130. data/lib/active_record/timestamp.rb +95 -52
  131. data/lib/active_record/transactions.rb +212 -66
  132. data/lib/active_record/translation.rb +22 -0
  133. data/lib/active_record/validations/associated.rb +43 -0
  134. data/lib/active_record/validations/uniqueness.rb +180 -0
  135. data/lib/active_record/validations.rb +43 -1106
  136. data/lib/active_record/version.rb +5 -4
  137. data/lib/active_record.rb +121 -48
  138. data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
  139. data/lib/rails/generators/active_record/migration/templates/migration.rb +34 -0
  140. data/lib/rails/generators/active_record/migration.rb +15 -0
  141. data/lib/rails/generators/active_record/model/model_generator.rb +47 -0
  142. data/lib/rails/generators/active_record/model/templates/migration.rb +15 -0
  143. data/lib/rails/generators/active_record/model/templates/model.rb +12 -0
  144. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  145. data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
  146. data/lib/rails/generators/active_record/observer/templates/observer.rb +4 -0
  147. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +25 -0
  148. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +12 -0
  149. data/lib/rails/generators/active_record.rb +25 -0
  150. metadata +187 -363
  151. data/CHANGELOG +0 -5904
  152. data/README +0 -351
  153. data/RUNNING_UNIT_TESTS +0 -36
  154. data/Rakefile +0 -268
  155. data/install.rb +0 -30
  156. data/lib/active_record/association_preload.rb +0 -406
  157. data/lib/active_record/associations/association_collection.rb +0 -533
  158. data/lib/active_record/associations/association_proxy.rb +0 -288
  159. data/lib/active_record/batches.rb +0 -85
  160. data/lib/active_record/calculations.rb +0 -321
  161. data/lib/active_record/dirty.rb +0 -183
  162. data/lib/active_record/named_scope.rb +0 -197
  163. data/lib/active_record/serializers/json_serializer.rb +0 -91
  164. data/lib/activerecord.rb +0 -2
  165. data/test/assets/example.log +0 -1
  166. data/test/assets/flowers.jpg +0 -0
  167. data/test/cases/aaa_create_tables_test.rb +0 -24
  168. data/test/cases/active_schema_test_mysql.rb +0 -122
  169. data/test/cases/active_schema_test_postgresql.rb +0 -24
  170. data/test/cases/adapter_test.rb +0 -144
  171. data/test/cases/aggregations_test.rb +0 -167
  172. data/test/cases/ar_schema_test.rb +0 -32
  173. data/test/cases/associations/belongs_to_associations_test.rb +0 -438
  174. data/test/cases/associations/callbacks_test.rb +0 -161
  175. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
  176. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
  177. data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
  178. data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
  179. data/test/cases/associations/eager_singularization_test.rb +0 -145
  180. data/test/cases/associations/eager_test.rb +0 -852
  181. data/test/cases/associations/extension_test.rb +0 -62
  182. data/test/cases/associations/habtm_join_table_test.rb +0 -56
  183. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
  184. data/test/cases/associations/has_many_associations_test.rb +0 -1273
  185. data/test/cases/associations/has_many_through_associations_test.rb +0 -360
  186. data/test/cases/associations/has_one_associations_test.rb +0 -330
  187. data/test/cases/associations/has_one_through_associations_test.rb +0 -209
  188. data/test/cases/associations/inner_join_association_test.rb +0 -93
  189. data/test/cases/associations/inverse_associations_test.rb +0 -566
  190. data/test/cases/associations/join_model_test.rb +0 -712
  191. data/test/cases/associations_test.rb +0 -282
  192. data/test/cases/attribute_methods_test.rb +0 -305
  193. data/test/cases/autosave_association_test.rb +0 -1218
  194. data/test/cases/base_test.rb +0 -2166
  195. data/test/cases/batches_test.rb +0 -81
  196. data/test/cases/binary_test.rb +0 -30
  197. data/test/cases/calculations_test.rb +0 -360
  198. data/test/cases/callbacks_observers_test.rb +0 -38
  199. data/test/cases/callbacks_test.rb +0 -438
  200. data/test/cases/class_inheritable_attributes_test.rb +0 -32
  201. data/test/cases/column_alias_test.rb +0 -17
  202. data/test/cases/column_definition_test.rb +0 -70
  203. data/test/cases/connection_pool_test.rb +0 -25
  204. data/test/cases/connection_test_firebird.rb +0 -8
  205. data/test/cases/connection_test_mysql.rb +0 -65
  206. data/test/cases/copy_table_test_sqlite.rb +0 -80
  207. data/test/cases/counter_cache_test.rb +0 -84
  208. data/test/cases/database_statements_test.rb +0 -12
  209. data/test/cases/datatype_test_postgresql.rb +0 -204
  210. data/test/cases/date_time_test.rb +0 -37
  211. data/test/cases/default_test_firebird.rb +0 -16
  212. data/test/cases/defaults_test.rb +0 -111
  213. data/test/cases/deprecated_finder_test.rb +0 -30
  214. data/test/cases/dirty_test.rb +0 -316
  215. data/test/cases/finder_respond_to_test.rb +0 -76
  216. data/test/cases/finder_test.rb +0 -1098
  217. data/test/cases/fixtures_test.rb +0 -661
  218. data/test/cases/helper.rb +0 -68
  219. data/test/cases/i18n_test.rb +0 -46
  220. data/test/cases/inheritance_test.rb +0 -262
  221. data/test/cases/invalid_date_test.rb +0 -24
  222. data/test/cases/json_serialization_test.rb +0 -219
  223. data/test/cases/lifecycle_test.rb +0 -193
  224. data/test/cases/locking_test.rb +0 -350
  225. data/test/cases/method_scoping_test.rb +0 -704
  226. data/test/cases/migration_test.rb +0 -1649
  227. data/test/cases/migration_test_firebird.rb +0 -124
  228. data/test/cases/mixin_test.rb +0 -96
  229. data/test/cases/modules_test.rb +0 -109
  230. data/test/cases/multiple_db_test.rb +0 -85
  231. data/test/cases/named_scope_test.rb +0 -372
  232. data/test/cases/nested_attributes_test.rb +0 -840
  233. data/test/cases/pk_test.rb +0 -119
  234. data/test/cases/pooled_connections_test.rb +0 -103
  235. data/test/cases/query_cache_test.rb +0 -129
  236. data/test/cases/readonly_test.rb +0 -107
  237. data/test/cases/reflection_test.rb +0 -234
  238. data/test/cases/reload_models_test.rb +0 -22
  239. data/test/cases/repair_helper.rb +0 -50
  240. data/test/cases/reserved_word_test_mysql.rb +0 -176
  241. data/test/cases/sanitize_test.rb +0 -25
  242. data/test/cases/schema_authorization_test_postgresql.rb +0 -75
  243. data/test/cases/schema_dumper_test.rb +0 -211
  244. data/test/cases/schema_test_postgresql.rb +0 -178
  245. data/test/cases/serialization_test.rb +0 -47
  246. data/test/cases/sp_test_mysql.rb +0 -16
  247. data/test/cases/synonym_test_oracle.rb +0 -17
  248. data/test/cases/timestamp_test.rb +0 -75
  249. data/test/cases/transactions_test.rb +0 -543
  250. data/test/cases/unconnected_test.rb +0 -32
  251. data/test/cases/validations_i18n_test.rb +0 -925
  252. data/test/cases/validations_test.rb +0 -1684
  253. data/test/cases/xml_serialization_test.rb +0 -240
  254. data/test/cases/yaml_serialization_test.rb +0 -11
  255. data/test/config.rb +0 -5
  256. data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
  257. data/test/connections/jdbc_jdbch2/connection.rb +0 -18
  258. data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
  259. data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
  260. data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
  261. data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
  262. data/test/connections/native_db2/connection.rb +0 -25
  263. data/test/connections/native_firebird/connection.rb +0 -26
  264. data/test/connections/native_frontbase/connection.rb +0 -27
  265. data/test/connections/native_mysql/connection.rb +0 -25
  266. data/test/connections/native_openbase/connection.rb +0 -21
  267. data/test/connections/native_oracle/connection.rb +0 -27
  268. data/test/connections/native_postgresql/connection.rb +0 -21
  269. data/test/connections/native_sqlite/connection.rb +0 -25
  270. data/test/connections/native_sqlite3/connection.rb +0 -25
  271. data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
  272. data/test/connections/native_sybase/connection.rb +0 -23
  273. data/test/fixtures/accounts.yml +0 -29
  274. data/test/fixtures/all/developers.yml +0 -0
  275. data/test/fixtures/all/people.csv +0 -0
  276. data/test/fixtures/all/tasks.yml +0 -0
  277. data/test/fixtures/author_addresses.yml +0 -5
  278. data/test/fixtures/author_favorites.yml +0 -4
  279. data/test/fixtures/authors.yml +0 -9
  280. data/test/fixtures/binaries.yml +0 -132
  281. data/test/fixtures/books.yml +0 -7
  282. data/test/fixtures/categories/special_categories.yml +0 -9
  283. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
  284. data/test/fixtures/categories.yml +0 -14
  285. data/test/fixtures/categories_ordered.yml +0 -7
  286. data/test/fixtures/categories_posts.yml +0 -23
  287. data/test/fixtures/categorizations.yml +0 -17
  288. data/test/fixtures/clubs.yml +0 -6
  289. data/test/fixtures/comments.yml +0 -59
  290. data/test/fixtures/companies.yml +0 -56
  291. data/test/fixtures/computers.yml +0 -4
  292. data/test/fixtures/courses.yml +0 -7
  293. data/test/fixtures/customers.yml +0 -26
  294. data/test/fixtures/developers.yml +0 -21
  295. data/test/fixtures/developers_projects.yml +0 -17
  296. data/test/fixtures/edges.yml +0 -6
  297. data/test/fixtures/entrants.yml +0 -14
  298. data/test/fixtures/faces.yml +0 -11
  299. data/test/fixtures/fk_test_has_fk.yml +0 -3
  300. data/test/fixtures/fk_test_has_pk.yml +0 -2
  301. data/test/fixtures/funny_jokes.yml +0 -10
  302. data/test/fixtures/interests.yml +0 -33
  303. data/test/fixtures/items.yml +0 -4
  304. data/test/fixtures/jobs.yml +0 -7
  305. data/test/fixtures/legacy_things.yml +0 -3
  306. data/test/fixtures/mateys.yml +0 -4
  307. data/test/fixtures/member_types.yml +0 -6
  308. data/test/fixtures/members.yml +0 -6
  309. data/test/fixtures/memberships.yml +0 -20
  310. data/test/fixtures/men.yml +0 -5
  311. data/test/fixtures/minimalistics.yml +0 -2
  312. data/test/fixtures/mixed_case_monkeys.yml +0 -6
  313. data/test/fixtures/mixins.yml +0 -29
  314. data/test/fixtures/movies.yml +0 -7
  315. data/test/fixtures/naked/csv/accounts.csv +0 -1
  316. data/test/fixtures/naked/yml/accounts.yml +0 -1
  317. data/test/fixtures/naked/yml/companies.yml +0 -1
  318. data/test/fixtures/naked/yml/courses.yml +0 -1
  319. data/test/fixtures/organizations.yml +0 -5
  320. data/test/fixtures/owners.yml +0 -7
  321. data/test/fixtures/parrots.yml +0 -27
  322. data/test/fixtures/parrots_pirates.yml +0 -7
  323. data/test/fixtures/people.yml +0 -15
  324. data/test/fixtures/pets.yml +0 -14
  325. data/test/fixtures/pirates.yml +0 -9
  326. data/test/fixtures/polymorphic_designs.yml +0 -19
  327. data/test/fixtures/polymorphic_prices.yml +0 -19
  328. data/test/fixtures/posts.yml +0 -52
  329. data/test/fixtures/price_estimates.yml +0 -7
  330. data/test/fixtures/projects.yml +0 -7
  331. data/test/fixtures/readers.yml +0 -9
  332. data/test/fixtures/references.yml +0 -17
  333. data/test/fixtures/reserved_words/distinct.yml +0 -5
  334. data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
  335. data/test/fixtures/reserved_words/group.yml +0 -14
  336. data/test/fixtures/reserved_words/select.yml +0 -8
  337. data/test/fixtures/reserved_words/values.yml +0 -7
  338. data/test/fixtures/ships.yml +0 -5
  339. data/test/fixtures/sponsors.yml +0 -9
  340. data/test/fixtures/subscribers.yml +0 -7
  341. data/test/fixtures/subscriptions.yml +0 -12
  342. data/test/fixtures/taggings.yml +0 -28
  343. data/test/fixtures/tags.yml +0 -7
  344. data/test/fixtures/tasks.yml +0 -7
  345. data/test/fixtures/tees.yml +0 -4
  346. data/test/fixtures/ties.yml +0 -4
  347. data/test/fixtures/topics.yml +0 -42
  348. data/test/fixtures/toys.yml +0 -4
  349. data/test/fixtures/treasures.yml +0 -10
  350. data/test/fixtures/vertices.yml +0 -4
  351. data/test/fixtures/warehouse-things.yml +0 -3
  352. data/test/fixtures/zines.yml +0 -5
  353. data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
  354. data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
  355. data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
  356. data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
  357. data/test/migrations/duplicate/3_foo.rb +0 -7
  358. data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
  359. data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
  360. data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
  361. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
  362. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
  363. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
  364. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
  365. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
  366. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
  367. data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
  368. data/test/migrations/missing/1_people_have_last_names.rb +0 -9
  369. data/test/migrations/missing/3_we_need_reminders.rb +0 -12
  370. data/test/migrations/missing/4_innocent_jointable.rb +0 -12
  371. data/test/migrations/valid/1_people_have_last_names.rb +0 -9
  372. data/test/migrations/valid/2_we_need_reminders.rb +0 -12
  373. data/test/migrations/valid/3_innocent_jointable.rb +0 -12
  374. data/test/models/author.rb +0 -151
  375. data/test/models/auto_id.rb +0 -4
  376. data/test/models/binary.rb +0 -2
  377. data/test/models/bird.rb +0 -9
  378. data/test/models/book.rb +0 -4
  379. data/test/models/categorization.rb +0 -5
  380. data/test/models/category.rb +0 -34
  381. data/test/models/citation.rb +0 -6
  382. data/test/models/club.rb +0 -13
  383. data/test/models/column_name.rb +0 -3
  384. data/test/models/comment.rb +0 -29
  385. data/test/models/company.rb +0 -173
  386. data/test/models/company_in_module.rb +0 -78
  387. data/test/models/computer.rb +0 -3
  388. data/test/models/contact.rb +0 -16
  389. data/test/models/contract.rb +0 -5
  390. data/test/models/course.rb +0 -3
  391. data/test/models/customer.rb +0 -73
  392. data/test/models/default.rb +0 -2
  393. data/test/models/developer.rb +0 -101
  394. data/test/models/edge.rb +0 -5
  395. data/test/models/entrant.rb +0 -3
  396. data/test/models/essay.rb +0 -3
  397. data/test/models/event.rb +0 -3
  398. data/test/models/event_author.rb +0 -8
  399. data/test/models/face.rb +0 -7
  400. data/test/models/guid.rb +0 -2
  401. data/test/models/interest.rb +0 -5
  402. data/test/models/invoice.rb +0 -4
  403. data/test/models/item.rb +0 -7
  404. data/test/models/job.rb +0 -5
  405. data/test/models/joke.rb +0 -3
  406. data/test/models/keyboard.rb +0 -3
  407. data/test/models/legacy_thing.rb +0 -3
  408. data/test/models/line_item.rb +0 -3
  409. data/test/models/man.rb +0 -9
  410. data/test/models/matey.rb +0 -4
  411. data/test/models/member.rb +0 -12
  412. data/test/models/member_detail.rb +0 -5
  413. data/test/models/member_type.rb +0 -3
  414. data/test/models/membership.rb +0 -9
  415. data/test/models/minimalistic.rb +0 -2
  416. data/test/models/mixed_case_monkey.rb +0 -3
  417. data/test/models/movie.rb +0 -5
  418. data/test/models/order.rb +0 -4
  419. data/test/models/organization.rb +0 -6
  420. data/test/models/owner.rb +0 -5
  421. data/test/models/parrot.rb +0 -22
  422. data/test/models/person.rb +0 -16
  423. data/test/models/pet.rb +0 -5
  424. data/test/models/pirate.rb +0 -80
  425. data/test/models/polymorphic_design.rb +0 -3
  426. data/test/models/polymorphic_price.rb +0 -3
  427. data/test/models/post.rb +0 -102
  428. data/test/models/price_estimate.rb +0 -3
  429. data/test/models/project.rb +0 -30
  430. data/test/models/reader.rb +0 -4
  431. data/test/models/reference.rb +0 -4
  432. data/test/models/reply.rb +0 -46
  433. data/test/models/ship.rb +0 -19
  434. data/test/models/ship_part.rb +0 -7
  435. data/test/models/sponsor.rb +0 -4
  436. data/test/models/subject.rb +0 -4
  437. data/test/models/subscriber.rb +0 -8
  438. data/test/models/subscription.rb +0 -4
  439. data/test/models/tag.rb +0 -7
  440. data/test/models/tagging.rb +0 -10
  441. data/test/models/task.rb +0 -3
  442. data/test/models/tee.rb +0 -4
  443. data/test/models/tie.rb +0 -4
  444. data/test/models/topic.rb +0 -80
  445. data/test/models/toy.rb +0 -6
  446. data/test/models/treasure.rb +0 -8
  447. data/test/models/vertex.rb +0 -9
  448. data/test/models/warehouse_thing.rb +0 -5
  449. data/test/models/zine.rb +0 -3
  450. data/test/schema/mysql_specific_schema.rb +0 -31
  451. data/test/schema/postgresql_specific_schema.rb +0 -114
  452. data/test/schema/schema.rb +0 -550
  453. data/test/schema/schema2.rb +0 -6
  454. data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,5 +1,10 @@
1
+ require 'active_support/core_ext/array/wrap'
2
+ require 'active_support/core_ext/hash/conversions'
3
+
1
4
  module ActiveRecord #:nodoc:
2
5
  module Serialization
6
+ include ActiveModel::Serializers::Xml
7
+
3
8
  # Builds an XML document to represent the model. Some configuration is
4
9
  # available through +options+. However more complicated cases should
5
10
  # override ActiveRecord::Base#to_xml.
@@ -69,6 +74,21 @@ module ActiveRecord #:nodoc:
69
74
  # </account>
70
75
  # </firm>
71
76
  #
77
+ # Additionally, the record being serialized will be passed to a Proc's second
78
+ # parameter. This allows for ad hoc additions to the resultant document that
79
+ # incorporate the context of the record being serialized. And by leveraging the
80
+ # closure created by a Proc, to_xml can be used to add elements that normally fall
81
+ # outside of the scope of the model -- for example, generating and appending URLs
82
+ # associated with models.
83
+ #
84
+ # proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
85
+ # firm.to_xml :procs => [ proc ]
86
+ #
87
+ # <firm>
88
+ # # ... normal attributes as shown above ...
89
+ # <name-reverse>slangis73</name-reverse>
90
+ # </firm>
91
+ #
72
92
  # To include deeper levels of associations pass a hash like this:
73
93
  #
74
94
  # firm.to_xml :include => {:account => {}, :clients => {:include => :address}}
@@ -143,8 +163,9 @@ module ActiveRecord #:nodoc:
143
163
  #
144
164
  # class IHaveMyOwnXML < ActiveRecord::Base
145
165
  # def to_xml(options = {})
166
+ # require 'builder'
146
167
  # options[:indent] ||= 2
147
- # xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
168
+ # xml = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
148
169
  # xml.instruct! unless options[:skip_instruct]
149
170
  # xml.level_one do
150
171
  # xml.tag!(:second_level, 'content')
@@ -152,206 +173,31 @@ module ActiveRecord #:nodoc:
152
173
  # end
153
174
  # end
154
175
  def to_xml(options = {}, &block)
155
- serializer = XmlSerializer.new(self, options)
156
- block_given? ? serializer.to_s(&block) : serializer.to_s
157
- end
158
-
159
- def from_xml(xml)
160
- self.attributes = Hash.from_xml(xml).values.first
161
- self
176
+ XmlSerializer.new(self, options).serialize(&block)
162
177
  end
163
178
  end
164
179
 
165
- class XmlSerializer < ActiveRecord::Serialization::Serializer #:nodoc:
166
- def builder
167
- @builder ||= begin
168
- options[:indent] ||= 2
169
- builder = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
170
-
171
- unless options[:skip_instruct]
172
- builder.instruct!
173
- options[:skip_instruct] = true
174
- end
175
-
176
- builder
180
+ class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc:
181
+ def initialize(*args)
182
+ super
183
+ options[:except] = Array.wrap(options[:except]) | Array.wrap(@serializable.class.inheritance_column)
184
+ end
185
+
186
+ class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
187
+ def compute_type
188
+ klass = @serializable.class
189
+ type = if klass.serialized_attributes.key?(name)
190
+ super
191
+ elsif klass.columns_hash.key?(name)
192
+ klass.columns_hash[name].type
193
+ else
194
+ NilClass
195
+ end
196
+
197
+ { :text => :string,
198
+ :time => :datetime }[type] || type
177
199
  end
178
- end
179
-
180
- def root
181
- root = (options[:root] || @record.class.model_name.singular).to_s
182
- reformat_name(root)
183
- end
184
-
185
- def dasherize?
186
- !options.has_key?(:dasherize) || options[:dasherize]
187
- end
188
-
189
- def camelize?
190
- options.has_key?(:camelize) && options[:camelize]
191
- end
192
-
193
- def reformat_name(name)
194
- name = name.camelize if camelize?
195
- dasherize? ? name.dasherize : name
196
- end
197
-
198
- def serializable_attributes
199
- serializable_attribute_names.collect { |name| Attribute.new(name, @record) }
200
- end
201
-
202
- def serializable_method_attributes
203
- Array(options[:methods]).inject([]) do |method_attributes, name|
204
- method_attributes << MethodAttribute.new(name.to_s, @record) if @record.respond_to?(name.to_s)
205
- method_attributes
206
- end
207
- end
208
-
209
- def add_attributes
210
- (serializable_attributes + serializable_method_attributes).each do |attribute|
211
- add_tag(attribute)
212
- end
213
- end
214
-
215
- def add_procs
216
- if procs = options.delete(:procs)
217
- [ *procs ].each do |proc|
218
- proc.call(options)
219
- end
220
- end
221
- end
222
-
223
- def add_tag(attribute)
224
- builder.tag!(
225
- reformat_name(attribute.name),
226
- attribute.value.to_s,
227
- attribute.decorations(!options[:skip_types])
228
- )
229
- end
230
-
231
- def add_associations(association, records, opts)
232
- if records.is_a?(Enumerable)
233
- tag = reformat_name(association.to_s)
234
- type = options[:skip_types] ? {} : {:type => "array"}
235
-
236
- if records.empty?
237
- builder.tag!(tag, type)
238
- else
239
- builder.tag!(tag, type) do
240
- association_name = association.to_s.singularize
241
- records.each do |record|
242
- if options[:skip_types]
243
- record_type = {}
244
- else
245
- record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name
246
- record_type = {:type => record_class}
247
- end
248
-
249
- record.to_xml opts.merge(:root => association_name).merge(record_type)
250
- end
251
- end
252
- end
253
- else
254
- if record = @record.send(association)
255
- record.to_xml(opts.merge(:root => association))
256
- end
257
- end
258
- end
259
-
260
- def serialize
261
- args = [root]
262
- if options[:namespace]
263
- args << {:xmlns=>options[:namespace]}
264
- end
265
-
266
- if options[:type]
267
- args << {:type=>options[:type]}
268
- end
269
-
270
- builder.tag!(*args) do
271
- add_attributes
272
- procs = options.delete(:procs)
273
- add_includes { |association, records, opts| add_associations(association, records, opts) }
274
- options[:procs] = procs
275
- add_procs
276
- yield builder if block_given?
277
- end
278
- end
279
-
280
- class Attribute #:nodoc:
281
- attr_reader :name, :value, :type
282
-
283
- def initialize(name, record)
284
- @name, @record = name, record
285
-
286
- @type = compute_type
287
- @value = compute_value
288
- end
289
-
290
- # There is a significant speed improvement if the value
291
- # does not need to be escaped, as <tt>tag!</tt> escapes all values
292
- # to ensure that valid XML is generated. For known binary
293
- # values, it is at least an order of magnitude faster to
294
- # Base64 encode binary values and directly put them in the
295
- # output XML than to pass the original value or the Base64
296
- # encoded value to the <tt>tag!</tt> method. It definitely makes
297
- # no sense to Base64 encode the value and then give it to
298
- # <tt>tag!</tt>, since that just adds additional overhead.
299
- def needs_encoding?
300
- ![ :binary, :date, :datetime, :boolean, :float, :integer ].include?(type)
301
- end
302
-
303
- def decorations(include_types = true)
304
- decorations = {}
305
-
306
- if type == :binary
307
- decorations[:encoding] = 'base64'
308
- end
309
-
310
- if include_types && type != :string
311
- decorations[:type] = type
312
- end
313
-
314
- if value.nil?
315
- decorations[:nil] = true
316
- end
317
-
318
- decorations
319
- end
320
-
321
- protected
322
- def compute_type
323
- type = if @record.class.serialized_attributes.has_key?(name)
324
- :yaml
325
- else
326
- @record.class.columns_hash[name].try(:type)
327
- end
328
-
329
- case type
330
- when :text
331
- :string
332
- when :time
333
- :datetime
334
- else
335
- type
336
- end
337
- end
338
-
339
- def compute_value
340
- value = @record.send(name)
341
-
342
- if formatter = Hash::XML_FORMATTING[type.to_s]
343
- value ? formatter.call(value) : nil
344
- else
345
- value
346
- end
347
- end
348
- end
349
-
350
- class MethodAttribute < Attribute #:nodoc:
351
- protected
352
- def compute_type
353
- Hash::XML_TYPE_NAMES[@record.send(name).class.name] || :string
354
- end
200
+ protected :compute_type
355
201
  end
356
202
  end
357
203
  end
@@ -1,24 +1,31 @@
1
+ require 'action_dispatch/middleware/session/abstract_store'
2
+
1
3
  module ActiveRecord
2
- # A session store backed by an Active Record class. A default class is
4
+ # = Active Record Session Store
5
+ #
6
+ # A session store backed by an Active Record class. A default class is
3
7
  # provided, but any object duck-typing to an Active Record Session class
4
8
  # with text +session_id+ and +data+ attributes is sufficient.
5
9
  #
6
10
  # The default assumes a +sessions+ tables with columns:
7
11
  # +id+ (numeric primary key),
8
- # +session_id+ (text, or longtext if your session data exceeds 65K), and
12
+ # +session_id+ (string, :limit => 255), and
9
13
  # +data+ (text or longtext; careful if your session data exceeds 65KB).
14
+ #
10
15
  # The +session_id+ column should always be indexed for speedy lookups.
11
16
  # Session data is marshaled to the +data+ column in Base64 format.
12
17
  # If the data you write is larger than the column's size limit,
13
18
  # ActionController::SessionOverflowError will be raised.
14
19
  #
15
20
  # You may configure the table name, primary key, and data column.
16
- # For example, at the end of <tt>config/environment.rb</tt>:
21
+ # For example, at the end of <tt>config/application.rb</tt>:
22
+ #
17
23
  # ActiveRecord::SessionStore::Session.table_name = 'legacy_session_table'
18
24
  # ActiveRecord::SessionStore::Session.primary_key = 'session_id'
19
25
  # ActiveRecord::SessionStore::Session.data_column_name = 'legacy_session_data'
26
+ #
20
27
  # Note that setting the primary key to the +session_id+ frees you from
21
- # having a separate +id+ column if you don't want it. However, you must
28
+ # having a separate +id+ column if you don't want it. However, you must
22
29
  # set <tt>session.model.id = session.session_id</tt> by hand! A before filter
23
30
  # on ApplicationController is a good place.
24
31
  #
@@ -29,32 +36,63 @@ module ActiveRecord
29
36
  # You may provide your own session class implementation, whether a
30
37
  # feature-packed Active Record or a bare-metal high-performance SQL
31
38
  # store, by setting
39
+ #
32
40
  # ActiveRecord::SessionStore.session_class = MySessionClass
41
+ #
33
42
  # You must implement these methods:
43
+ #
34
44
  # self.find_by_session_id(session_id)
35
- # initialize(hash_of_session_id_and_data)
45
+ # initialize(hash_of_session_id_and_data, options_hash = {})
36
46
  # attr_reader :session_id
37
47
  # attr_accessor :data
38
48
  # save
39
49
  # destroy
40
50
  #
41
- # The example SqlBypass class is a generic SQL session store. You may
51
+ # The example SqlBypass class is a generic SQL session store. You may
42
52
  # use it as a basis for high-performance database-specific stores.
43
- class SessionStore < ActionController::Session::AbstractStore
53
+ class SessionStore < ActionDispatch::Session::AbstractStore
54
+ module ClassMethods # :nodoc:
55
+ def marshal(data)
56
+ ::Base64.encode64(Marshal.dump(data)) if data
57
+ end
58
+
59
+ def unmarshal(data)
60
+ Marshal.load(::Base64.decode64(data)) if data
61
+ end
62
+
63
+ def drop_table!
64
+ connection.schema_cache.clear_table_cache!(table_name)
65
+ connection.drop_table table_name
66
+ end
67
+
68
+ def create_table!
69
+ connection.schema_cache.clear_table_cache!(table_name)
70
+ connection.create_table(table_name) do |t|
71
+ t.string session_id_column, :limit => 255
72
+ t.text data_column_name
73
+ end
74
+ connection.add_index table_name, session_id_column, :unique => true
75
+ end
76
+ end
77
+
44
78
  # The default Active Record class.
45
79
  class Session < ActiveRecord::Base
80
+ extend ClassMethods
81
+
46
82
  ##
47
83
  # :singleton-method:
48
- # Customizable data column name. Defaults to 'data'.
84
+ # Customizable data column name. Defaults to 'data'.
49
85
  cattr_accessor :data_column_name
50
86
  self.data_column_name = 'data'
51
87
 
88
+ attr_accessible :session_id, :data, :marshaled_data
89
+
52
90
  before_save :marshal_data!
53
91
  before_save :raise_on_session_data_overflow!
54
92
 
55
93
  class << self
56
94
  def data_column_size_limit
57
- @data_column_size_limit ||= columns_hash[@@data_column_name].limit
95
+ @data_column_size_limit ||= columns_hash[data_column_name].limit
58
96
  end
59
97
 
60
98
  # Hook to set up sessid compatibility.
@@ -63,29 +101,11 @@ module ActiveRecord
63
101
  find_by_session_id(session_id)
64
102
  end
65
103
 
66
- def marshal(data)
67
- ActiveSupport::Base64.encode64(Marshal.dump(data)) if data
68
- end
69
-
70
- def unmarshal(data)
71
- Marshal.load(ActiveSupport::Base64.decode64(data)) if data
72
- end
73
-
74
- def create_table!
75
- connection.execute <<-end_sql
76
- CREATE TABLE #{table_name} (
77
- id INTEGER PRIMARY KEY,
78
- #{connection.quote_column_name('session_id')} TEXT UNIQUE,
79
- #{connection.quote_column_name(@@data_column_name)} TEXT(255)
80
- )
81
- end_sql
82
- end
83
-
84
- def drop_table!
85
- connection.execute "DROP TABLE #{table_name}"
86
- end
87
-
88
104
  private
105
+ def session_id_column
106
+ 'session_id'
107
+ end
108
+
89
109
  # Compatibility with tables using sessid instead of session_id.
90
110
  def setup_sessid_compatibility!
91
111
  # Reset column info since it may be stale.
@@ -98,6 +118,8 @@ module ActiveRecord
98
118
  define_method(:session_id) { sessid }
99
119
  define_method(:session_id=) { |session_id| self.sessid = session_id }
100
120
  else
121
+ class << self; remove_method :find_by_session_id; end
122
+
101
123
  def self.find_by_session_id(session_id)
102
124
  find :first, :conditions => {:session_id=>session_id}
103
125
  end
@@ -105,6 +127,11 @@ module ActiveRecord
105
127
  end
106
128
  end
107
129
 
130
+ def initialize(attributes = nil, options = {})
131
+ @data = nil
132
+ super
133
+ end
134
+
108
135
  # Lazy-unmarshal session state.
109
136
  def data
110
137
  @data ||= self.class.unmarshal(read_attribute(@@data_column_name)) || {}
@@ -114,50 +141,47 @@ module ActiveRecord
114
141
 
115
142
  # Has the session been loaded yet?
116
143
  def loaded?
117
- !!@data
144
+ @data
118
145
  end
119
146
 
120
147
  private
121
148
  def marshal_data!
122
- return false if !loaded?
123
- write_attribute(@@data_column_name, self.class.marshal(self.data))
149
+ return false unless loaded?
150
+ write_attribute(@@data_column_name, self.class.marshal(data))
124
151
  end
125
152
 
126
153
  # Ensures that the data about to be stored in the database is not
127
154
  # larger than the data storage column. Raises
128
155
  # ActionController::SessionOverflowError.
129
156
  def raise_on_session_data_overflow!
130
- return false if !loaded?
157
+ return false unless loaded?
131
158
  limit = self.class.data_column_size_limit
132
- if loaded? and limit and read_attribute(@@data_column_name).size > limit
159
+ if limit and read_attribute(@@data_column_name).size > limit
133
160
  raise ActionController::SessionOverflowError
134
161
  end
135
162
  end
136
163
  end
137
164
 
138
165
  # A barebones session store which duck-types with the default session
139
- # store but bypasses Active Record and issues SQL directly. This is
166
+ # store but bypasses Active Record and issues SQL directly. This is
140
167
  # an example session model class meant as a basis for your own classes.
141
168
  #
142
169
  # The database connection, table name, and session id and data columns
143
- # are configurable class attributes. Marshaling and unmarshaling
144
- # are implemented as class methods that you may override. By default,
170
+ # are configurable class attributes. Marshaling and unmarshaling
171
+ # are implemented as class methods that you may override. By default,
145
172
  # marshaling data is
146
173
  #
147
- # ActiveSupport::Base64.encode64(Marshal.dump(data))
174
+ # ::Base64.encode64(Marshal.dump(data))
148
175
  #
149
176
  # and unmarshaling data is
150
177
  #
151
- # Marshal.load(ActiveSupport::Base64.decode64(data))
178
+ # Marshal.load(::Base64.decode64(data))
152
179
  #
153
180
  # This marshaling behavior is intended to store the widest range of
154
- # binary session data in a +text+ column. For higher performance,
181
+ # binary session data in a +text+ column. For higher performance,
155
182
  # store in a +blob+ column instead and forgo the Base64 encoding.
156
183
  class SqlBypass
157
- ##
158
- # :singleton-method:
159
- # Use the ActiveRecord::Base.connection by default.
160
- cattr_accessor :connection
184
+ extend ClassMethods
161
185
 
162
186
  ##
163
187
  # :singleton-method:
@@ -178,8 +202,20 @@ module ActiveRecord
178
202
  @@data_column = 'data'
179
203
 
180
204
  class << self
205
+ alias :data_column_name :data_column
206
+
207
+ # Use the ActiveRecord::Base.connection by default.
208
+ attr_writer :connection
209
+
210
+ # Use the ActiveRecord::Base.connection_pool by default.
211
+ attr_writer :connection_pool
212
+
181
213
  def connection
182
- @@connection ||= ActiveRecord::Base.connection
214
+ @connection ||= ActiveRecord::Base.connection
215
+ end
216
+
217
+ def connection_pool
218
+ @connection_pool ||= ActiveRecord::Base.connection_pool
183
219
  end
184
220
 
185
221
  # Look up a session by id and unmarshal its data if found.
@@ -188,43 +224,23 @@ module ActiveRecord
188
224
  new(:session_id => session_id, :marshaled_data => record['data'])
189
225
  end
190
226
  end
191
-
192
- def marshal(data)
193
- ActiveSupport::Base64.encode64(Marshal.dump(data)) if data
194
- end
195
-
196
- def unmarshal(data)
197
- Marshal.load(ActiveSupport::Base64.decode64(data)) if data
198
- end
199
-
200
- def create_table!
201
- @@connection.execute <<-end_sql
202
- CREATE TABLE #{table_name} (
203
- id INTEGER PRIMARY KEY,
204
- #{@@connection.quote_column_name(session_id_column)} TEXT UNIQUE,
205
- #{@@connection.quote_column_name(data_column)} TEXT
206
- )
207
- end_sql
208
- end
209
-
210
- def drop_table!
211
- @@connection.execute "DROP TABLE #{table_name}"
212
- end
213
227
  end
228
+
229
+ delegate :connection, :connection=, :connection_pool, :connection_pool=, :to => self
230
+
231
+ attr_reader :session_id, :new_record
232
+ alias :new_record? :new_record
214
233
 
215
- attr_reader :session_id
216
234
  attr_writer :data
217
235
 
218
236
  # Look for normal and marshaled data, self.find_by_session_id's way of
219
237
  # telling us to postpone unmarshaling until the data is requested.
220
238
  # We need to handle a normal data attribute in case of a new record.
221
239
  def initialize(attributes)
222
- @session_id, @data, @marshaled_data = attributes[:session_id], attributes[:data], attributes[:marshaled_data]
223
- @new_record = @marshaled_data.nil?
224
- end
225
-
226
- def new_record?
227
- @new_record
240
+ @session_id = attributes[:session_id]
241
+ @data = attributes[:data]
242
+ @marshaled_data = attributes[:marshaled_data]
243
+ @new_record = @marshaled_data.nil?
228
244
  end
229
245
 
230
246
  # Lazy-unmarshal session state.
@@ -240,60 +256,67 @@ module ActiveRecord
240
256
  end
241
257
 
242
258
  def loaded?
243
- !!@data
259
+ @data
244
260
  end
245
261
 
246
262
  def save
247
- return false if !loaded?
263
+ return false unless loaded?
248
264
  marshaled_data = self.class.marshal(data)
265
+ connect = connection
249
266
 
250
267
  if @new_record
251
268
  @new_record = false
252
- @@connection.update <<-end_sql, 'Create session'
253
- INSERT INTO #{@@table_name} (
254
- #{@@connection.quote_column_name(@@session_id_column)},
255
- #{@@connection.quote_column_name(@@data_column)} )
269
+ connect.update <<-end_sql, 'Create session'
270
+ INSERT INTO #{table_name} (
271
+ #{connect.quote_column_name(session_id_column)},
272
+ #{connect.quote_column_name(data_column)} )
256
273
  VALUES (
257
- #{@@connection.quote(session_id)},
258
- #{@@connection.quote(marshaled_data)} )
274
+ #{connect.quote(session_id)},
275
+ #{connect.quote(marshaled_data)} )
259
276
  end_sql
260
277
  else
261
- @@connection.update <<-end_sql, 'Update session'
262
- UPDATE #{@@table_name}
263
- SET #{@@connection.quote_column_name(@@data_column)}=#{@@connection.quote(marshaled_data)}
264
- WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)}
278
+ connect.update <<-end_sql, 'Update session'
279
+ UPDATE #{table_name}
280
+ SET #{connect.quote_column_name(data_column)}=#{connect.quote(marshaled_data)}
281
+ WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id)}
265
282
  end_sql
266
283
  end
267
284
  end
268
285
 
269
286
  def destroy
270
- unless @new_record
271
- @@connection.delete <<-end_sql, 'Destroy session'
272
- DELETE FROM #{@@table_name}
273
- WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)}
274
- end_sql
275
- end
287
+ return if @new_record
288
+
289
+ connect = connection
290
+ connect.delete <<-end_sql, 'Destroy session'
291
+ DELETE FROM #{table_name}
292
+ WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id)}
293
+ end_sql
276
294
  end
277
295
  end
278
296
 
279
- # The class used for session storage. Defaults to
297
+ # The class used for session storage. Defaults to
280
298
  # ActiveRecord::SessionStore::Session
281
299
  cattr_accessor :session_class
282
300
  self.session_class = Session
283
301
 
284
- SESSION_RECORD_KEY = 'rack.session.record'.freeze
302
+ SESSION_RECORD_KEY = 'rack.session.record'
303
+ ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY
285
304
 
286
305
  private
287
306
  def get_session(env, sid)
288
307
  Base.silence do
289
- sid ||= generate_sid
290
- session = find_session(sid)
308
+ unless sid and session = @@session_class.find_by_session_id(sid)
309
+ # If the sid was nil or if there is no pre-existing session under the sid,
310
+ # force the generation of a new sid and associate a new session associated with the new sid
311
+ sid = generate_sid
312
+ session = @@session_class.new(:session_id => sid, :data => {})
313
+ end
291
314
  env[SESSION_RECORD_KEY] = session
292
315
  [sid, session.data]
293
316
  end
294
317
  end
295
318
 
296
- def set_session(env, sid, session_data)
319
+ def set_session(env, sid, session_data, options)
297
320
  Base.silence do
298
321
  record = get_session_model(env, sid)
299
322
  record.data = session_data
@@ -307,17 +330,20 @@ module ActiveRecord
307
330
  end
308
331
  end
309
332
 
310
- return true
333
+ sid
311
334
  end
312
-
313
- def destroy(env)
335
+
336
+ def destroy_session(env, session_id, options)
314
337
  if sid = current_session_id(env)
315
338
  Base.silence do
316
339
  get_session_model(env, sid).destroy
340
+ env[SESSION_RECORD_KEY] = nil
317
341
  end
318
342
  end
343
+
344
+ generate_sid unless options[:drop]
319
345
  end
320
-
346
+
321
347
  def get_session_model(env, sid)
322
348
  if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
323
349
  env[SESSION_RECORD_KEY] = find_session(sid)