activerecord 1.0.0 → 4.0.0

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 (255) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2102 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +213 -0
  5. data/examples/performance.rb +172 -0
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record/aggregations.rb +180 -84
  8. data/lib/active_record/associations/alias_tracker.rb +76 -0
  9. data/lib/active_record/associations/association.rb +248 -0
  10. data/lib/active_record/associations/association_scope.rb +135 -0
  11. data/lib/active_record/associations/belongs_to_association.rb +92 -0
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +35 -0
  13. data/lib/active_record/associations/builder/association.rb +108 -0
  14. data/lib/active_record/associations/builder/belongs_to.rb +98 -0
  15. data/lib/active_record/associations/builder/collection_association.rb +89 -0
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
  17. data/lib/active_record/associations/builder/has_many.rb +15 -0
  18. data/lib/active_record/associations/builder/has_one.rb +25 -0
  19. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  20. data/lib/active_record/associations/collection_association.rb +608 -0
  21. data/lib/active_record/associations/collection_proxy.rb +986 -0
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +58 -39
  23. data/lib/active_record/associations/has_many_association.rb +116 -85
  24. data/lib/active_record/associations/has_many_through_association.rb +197 -0
  25. data/lib/active_record/associations/has_one_association.rb +102 -0
  26. data/lib/active_record/associations/has_one_through_association.rb +36 -0
  27. data/lib/active_record/associations/join_dependency/join_association.rb +174 -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 +235 -0
  31. data/lib/active_record/associations/join_helper.rb +45 -0
  32. data/lib/active_record/associations/preloader/association.rb +121 -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 +19 -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 +63 -0
  42. data/lib/active_record/associations/preloader.rb +178 -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 +1437 -431
  46. data/lib/active_record/attribute_assignment.rb +201 -0
  47. data/lib/active_record/attribute_methods/before_type_cast.rb +70 -0
  48. data/lib/active_record/attribute_methods/dirty.rb +118 -0
  49. data/lib/active_record/attribute_methods/primary_key.rb +122 -0
  50. data/lib/active_record/attribute_methods/query.rb +40 -0
  51. data/lib/active_record/attribute_methods/read.rb +107 -0
  52. data/lib/active_record/attribute_methods/serialization.rb +162 -0
  53. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -0
  54. data/lib/active_record/attribute_methods/write.rb +63 -0
  55. data/lib/active_record/attribute_methods.rb +393 -0
  56. data/lib/active_record/autosave_association.rb +426 -0
  57. data/lib/active_record/base.rb +268 -930
  58. data/lib/active_record/callbacks.rb +203 -230
  59. data/lib/active_record/coders/yaml_column.rb +38 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +638 -0
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +67 -0
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +390 -0
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -0
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +129 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +501 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +873 -0
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +389 -275
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
  71. data/lib/active_record/connection_adapters/column.rb +318 -0
  72. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  73. data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
  74. data/lib/active_record/connection_adapters/mysql_adapter.rb +517 -90
  75. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  76. data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
  77. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
  79. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
  80. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  81. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
  82. data/lib/active_record/connection_adapters/postgresql_adapter.rb +911 -138
  83. data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
  84. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +624 -0
  85. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  86. data/lib/active_record/connection_handling.rb +98 -0
  87. data/lib/active_record/core.rb +463 -0
  88. data/lib/active_record/counter_cache.rb +122 -0
  89. data/lib/active_record/dynamic_matchers.rb +131 -0
  90. data/lib/active_record/errors.rb +213 -0
  91. data/lib/active_record/explain.rb +38 -0
  92. data/lib/active_record/explain_registry.rb +30 -0
  93. data/lib/active_record/explain_subscriber.rb +29 -0
  94. data/lib/active_record/fixture_set/file.rb +55 -0
  95. data/lib/active_record/fixtures.rb +892 -138
  96. data/lib/active_record/inheritance.rb +200 -0
  97. data/lib/active_record/integration.rb +60 -0
  98. data/lib/active_record/locale/en.yml +47 -0
  99. data/lib/active_record/locking/optimistic.rb +181 -0
  100. data/lib/active_record/locking/pessimistic.rb +77 -0
  101. data/lib/active_record/log_subscriber.rb +82 -0
  102. data/lib/active_record/migration/command_recorder.rb +164 -0
  103. data/lib/active_record/migration/join_table.rb +15 -0
  104. data/lib/active_record/migration.rb +1015 -0
  105. data/lib/active_record/model_schema.rb +345 -0
  106. data/lib/active_record/nested_attributes.rb +546 -0
  107. data/lib/active_record/null_relation.rb +65 -0
  108. data/lib/active_record/persistence.rb +509 -0
  109. data/lib/active_record/query_cache.rb +56 -0
  110. data/lib/active_record/querying.rb +62 -0
  111. data/lib/active_record/railtie.rb +205 -0
  112. data/lib/active_record/railties/console_sandbox.rb +5 -0
  113. data/lib/active_record/railties/controller_runtime.rb +50 -0
  114. data/lib/active_record/railties/databases.rake +402 -0
  115. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  116. data/lib/active_record/readonly_attributes.rb +30 -0
  117. data/lib/active_record/reflection.rb +544 -87
  118. data/lib/active_record/relation/batches.rb +93 -0
  119. data/lib/active_record/relation/calculations.rb +399 -0
  120. data/lib/active_record/relation/delegation.rb +125 -0
  121. data/lib/active_record/relation/finder_methods.rb +349 -0
  122. data/lib/active_record/relation/merger.rb +161 -0
  123. data/lib/active_record/relation/predicate_builder.rb +106 -0
  124. data/lib/active_record/relation/query_methods.rb +1044 -0
  125. data/lib/active_record/relation/spawn_methods.rb +73 -0
  126. data/lib/active_record/relation.rb +655 -0
  127. data/lib/active_record/result.rb +67 -0
  128. data/lib/active_record/runtime_registry.rb +17 -0
  129. data/lib/active_record/sanitization.rb +168 -0
  130. data/lib/active_record/schema.rb +65 -0
  131. data/lib/active_record/schema_dumper.rb +204 -0
  132. data/lib/active_record/schema_migration.rb +39 -0
  133. data/lib/active_record/scoping/default.rb +146 -0
  134. data/lib/active_record/scoping/named.rb +175 -0
  135. data/lib/active_record/scoping.rb +82 -0
  136. data/lib/active_record/serialization.rb +22 -0
  137. data/lib/active_record/serializers/xml_serializer.rb +197 -0
  138. data/lib/active_record/statement_cache.rb +26 -0
  139. data/lib/active_record/store.rb +156 -0
  140. data/lib/active_record/tasks/database_tasks.rb +203 -0
  141. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  142. data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
  143. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  144. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  145. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  146. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  147. data/lib/active_record/test_case.rb +96 -0
  148. data/lib/active_record/timestamp.rb +119 -0
  149. data/lib/active_record/transactions.rb +366 -69
  150. data/lib/active_record/translation.rb +22 -0
  151. data/lib/active_record/validations/associated.rb +49 -0
  152. data/lib/active_record/validations/presence.rb +65 -0
  153. data/lib/active_record/validations/uniqueness.rb +225 -0
  154. data/lib/active_record/validations.rb +64 -185
  155. data/lib/active_record/version.rb +11 -0
  156. data/lib/active_record.rb +149 -24
  157. data/lib/rails/generators/active_record/migration/migration_generator.rb +62 -0
  158. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
  159. data/lib/rails/generators/active_record/migration/templates/migration.rb +39 -0
  160. data/lib/rails/generators/active_record/model/model_generator.rb +48 -0
  161. data/lib/rails/generators/active_record/model/templates/model.rb +10 -0
  162. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  163. data/lib/rails/generators/active_record.rb +23 -0
  164. metadata +261 -161
  165. data/CHANGELOG +0 -581
  166. data/README +0 -361
  167. data/RUNNING_UNIT_TESTS +0 -36
  168. data/dev-utils/eval_debugger.rb +0 -9
  169. data/examples/associations.png +0 -0
  170. data/examples/associations.rb +0 -87
  171. data/examples/shared_setup.rb +0 -15
  172. data/examples/validation.rb +0 -88
  173. data/install.rb +0 -60
  174. data/lib/active_record/associations/association_collection.rb +0 -70
  175. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -107
  176. data/lib/active_record/deprecated_associations.rb +0 -70
  177. data/lib/active_record/observer.rb +0 -71
  178. data/lib/active_record/support/class_attribute_accessors.rb +0 -43
  179. data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
  180. data/lib/active_record/support/clean_logger.rb +0 -10
  181. data/lib/active_record/support/inflector.rb +0 -70
  182. data/lib/active_record/vendor/mysql.rb +0 -1117
  183. data/lib/active_record/vendor/simple.rb +0 -702
  184. data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
  185. data/lib/active_record/wrappings.rb +0 -59
  186. data/rakefile +0 -122
  187. data/test/abstract_unit.rb +0 -16
  188. data/test/aggregations_test.rb +0 -34
  189. data/test/all.sh +0 -8
  190. data/test/associations_test.rb +0 -477
  191. data/test/base_test.rb +0 -513
  192. data/test/class_inheritable_attributes_test.rb +0 -33
  193. data/test/connections/native_mysql/connection.rb +0 -24
  194. data/test/connections/native_postgresql/connection.rb +0 -24
  195. data/test/connections/native_sqlite/connection.rb +0 -24
  196. data/test/deprecated_associations_test.rb +0 -336
  197. data/test/finder_test.rb +0 -67
  198. data/test/fixtures/accounts/signals37 +0 -3
  199. data/test/fixtures/accounts/unknown +0 -2
  200. data/test/fixtures/auto_id.rb +0 -4
  201. data/test/fixtures/column_name.rb +0 -3
  202. data/test/fixtures/companies/first_client +0 -6
  203. data/test/fixtures/companies/first_firm +0 -4
  204. data/test/fixtures/companies/second_client +0 -6
  205. data/test/fixtures/company.rb +0 -37
  206. data/test/fixtures/company_in_module.rb +0 -33
  207. data/test/fixtures/course.rb +0 -3
  208. data/test/fixtures/courses/java +0 -2
  209. data/test/fixtures/courses/ruby +0 -2
  210. data/test/fixtures/customer.rb +0 -30
  211. data/test/fixtures/customers/david +0 -6
  212. data/test/fixtures/db_definitions/mysql.sql +0 -96
  213. data/test/fixtures/db_definitions/mysql2.sql +0 -4
  214. data/test/fixtures/db_definitions/postgresql.sql +0 -113
  215. data/test/fixtures/db_definitions/postgresql2.sql +0 -4
  216. data/test/fixtures/db_definitions/sqlite.sql +0 -85
  217. data/test/fixtures/db_definitions/sqlite2.sql +0 -4
  218. data/test/fixtures/default.rb +0 -2
  219. data/test/fixtures/developer.rb +0 -8
  220. data/test/fixtures/developers/david +0 -2
  221. data/test/fixtures/developers/jamis +0 -2
  222. data/test/fixtures/developers_projects/david_action_controller +0 -2
  223. data/test/fixtures/developers_projects/david_active_record +0 -2
  224. data/test/fixtures/developers_projects/jamis_active_record +0 -2
  225. data/test/fixtures/entrant.rb +0 -3
  226. data/test/fixtures/entrants/first +0 -3
  227. data/test/fixtures/entrants/second +0 -3
  228. data/test/fixtures/entrants/third +0 -3
  229. data/test/fixtures/fixture_database.sqlite +0 -0
  230. data/test/fixtures/fixture_database_2.sqlite +0 -0
  231. data/test/fixtures/movie.rb +0 -5
  232. data/test/fixtures/movies/first +0 -2
  233. data/test/fixtures/movies/second +0 -2
  234. data/test/fixtures/project.rb +0 -3
  235. data/test/fixtures/projects/action_controller +0 -2
  236. data/test/fixtures/projects/active_record +0 -2
  237. data/test/fixtures/reply.rb +0 -21
  238. data/test/fixtures/subscriber.rb +0 -5
  239. data/test/fixtures/subscribers/first +0 -2
  240. data/test/fixtures/subscribers/second +0 -2
  241. data/test/fixtures/topic.rb +0 -20
  242. data/test/fixtures/topics/first +0 -9
  243. data/test/fixtures/topics/second +0 -8
  244. data/test/fixtures_test.rb +0 -20
  245. data/test/inflector_test.rb +0 -104
  246. data/test/inheritance_test.rb +0 -125
  247. data/test/lifecycle_test.rb +0 -110
  248. data/test/modules_test.rb +0 -21
  249. data/test/multiple_db_test.rb +0 -46
  250. data/test/pk_test.rb +0 -57
  251. data/test/reflection_test.rb +0 -78
  252. data/test/thread_safety_test.rb +0 -33
  253. data/test/transactions_test.rb +0 -83
  254. data/test/unconnected_test.rb +0 -24
  255. data/test/validations_test.rb +0 -126
@@ -0,0 +1,131 @@
1
+ module ActiveRecord
2
+ module DynamicMatchers #:nodoc:
3
+ # This code in this file seems to have a lot of indirection, but the indirection
4
+ # is there to provide extension points for the activerecord-deprecated_finders
5
+ # gem. When we stop supporting activerecord-deprecated_finders (from Rails 5),
6
+ # then we can remove the indirection.
7
+
8
+ def respond_to?(name, include_private = false)
9
+ match = Method.match(self, name)
10
+ match && match.valid? || super
11
+ end
12
+
13
+ private
14
+
15
+ def method_missing(name, *arguments, &block)
16
+ match = Method.match(self, name)
17
+
18
+ if match && match.valid?
19
+ match.define
20
+ send(name, *arguments, &block)
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ class Method
27
+ @matchers = []
28
+
29
+ class << self
30
+ attr_reader :matchers
31
+
32
+ def match(model, name)
33
+ klass = matchers.find { |k| name =~ k.pattern }
34
+ klass.new(model, name) if klass
35
+ end
36
+
37
+ def pattern
38
+ /^#{prefix}_([_a-zA-Z]\w*)#{suffix}$/
39
+ end
40
+
41
+ def prefix
42
+ raise NotImplementedError
43
+ end
44
+
45
+ def suffix
46
+ ''
47
+ end
48
+ end
49
+
50
+ attr_reader :model, :name, :attribute_names
51
+
52
+ def initialize(model, name)
53
+ @model = model
54
+ @name = name.to_s
55
+ @attribute_names = @name.match(self.class.pattern)[1].split('_and_')
56
+ @attribute_names.map! { |n| @model.attribute_aliases[n] || n }
57
+ end
58
+
59
+ def valid?
60
+ attribute_names.all? { |name| model.columns_hash[name] || model.reflect_on_aggregation(name.to_sym) }
61
+ end
62
+
63
+ def define
64
+ model.class_eval <<-CODE, __FILE__, __LINE__ + 1
65
+ def self.#{name}(#{signature})
66
+ #{body}
67
+ end
68
+ CODE
69
+ end
70
+
71
+ def body
72
+ raise NotImplementedError
73
+ end
74
+ end
75
+
76
+ module Finder
77
+ # Extended in activerecord-deprecated_finders
78
+ def body
79
+ result
80
+ end
81
+
82
+ # Extended in activerecord-deprecated_finders
83
+ def result
84
+ "#{finder}(#{attributes_hash})"
85
+ end
86
+
87
+ # Extended in activerecord-deprecated_finders
88
+ def signature
89
+ attribute_names.join(', ')
90
+ end
91
+
92
+ def attributes_hash
93
+ "{" + attribute_names.map { |name| ":#{name} => #{name}" }.join(',') + "}"
94
+ end
95
+
96
+ def finder
97
+ raise NotImplementedError
98
+ end
99
+ end
100
+
101
+ class FindBy < Method
102
+ Method.matchers << self
103
+ include Finder
104
+
105
+ def self.prefix
106
+ "find_by"
107
+ end
108
+
109
+ def finder
110
+ "find_by"
111
+ end
112
+ end
113
+
114
+ class FindByBang < Method
115
+ Method.matchers << self
116
+ include Finder
117
+
118
+ def self.prefix
119
+ "find_by"
120
+ end
121
+
122
+ def self.suffix
123
+ "!"
124
+ end
125
+
126
+ def finder
127
+ "find_by!"
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,213 @@
1
+ module ActiveRecord
2
+
3
+ # = Active Record Errors
4
+ #
5
+ # Generic Active Record exception class.
6
+ class ActiveRecordError < StandardError
7
+ end
8
+
9
+ # Raised when the single-table inheritance mechanism fails to locate the subclass
10
+ # (for example due to improper usage of column that +inheritance_column+ points to).
11
+ class SubclassNotFound < ActiveRecordError #:nodoc:
12
+ end
13
+
14
+ # Raised when an object assigned to an association has an incorrect type.
15
+ #
16
+ # class Ticket < ActiveRecord::Base
17
+ # has_many :patches
18
+ # end
19
+ #
20
+ # class Patch < ActiveRecord::Base
21
+ # belongs_to :ticket
22
+ # end
23
+ #
24
+ # # Comments are not patches, this assignment raises AssociationTypeMismatch.
25
+ # @ticket.patches << Comment.new(content: "Please attach tests to your patch.")
26
+ class AssociationTypeMismatch < ActiveRecordError
27
+ end
28
+
29
+ # Raised when unserialized object's type mismatches one specified for serializable field.
30
+ class SerializationTypeMismatch < ActiveRecordError
31
+ end
32
+
33
+ # Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt>
34
+ # misses adapter field).
35
+ class AdapterNotSpecified < ActiveRecordError
36
+ end
37
+
38
+ # Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
39
+ class AdapterNotFound < ActiveRecordError
40
+ end
41
+
42
+ # Raised when connection to the database could not been established (for example when <tt>connection=</tt>
43
+ # is given a nil object).
44
+ class ConnectionNotEstablished < ActiveRecordError
45
+ end
46
+
47
+ # Raised when Active Record cannot find record by given id or set of ids.
48
+ class RecordNotFound < ActiveRecordError
49
+ end
50
+
51
+ # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
52
+ # saved because record is invalid.
53
+ class RecordNotSaved < ActiveRecordError
54
+ end
55
+
56
+ # Raised by ActiveRecord::Base.destroy! when a call to destroy would return false.
57
+ class RecordNotDestroyed < ActiveRecordError
58
+ end
59
+
60
+ # Superclass for all database execution errors.
61
+ #
62
+ # Wraps the underlying database error as +original_exception+.
63
+ class StatementInvalid < ActiveRecordError
64
+ attr_reader :original_exception
65
+
66
+ def initialize(message, original_exception = nil)
67
+ super(message)
68
+ @original_exception = original_exception
69
+ end
70
+ end
71
+
72
+ # Raised when SQL statement is invalid and the application gets a blank result.
73
+ class ThrowResult < ActiveRecordError
74
+ end
75
+
76
+ # Defunct wrapper class kept for compatibility.
77
+ # +StatementInvalid+ wraps the original exception now.
78
+ class WrappedDatabaseException < StatementInvalid
79
+ end
80
+
81
+ # Raised when a record cannot be inserted because it would violate a uniqueness constraint.
82
+ class RecordNotUnique < WrappedDatabaseException
83
+ end
84
+
85
+ # Raised when a record cannot be inserted or updated because it references a non-existent record.
86
+ class InvalidForeignKey < WrappedDatabaseException
87
+ end
88
+
89
+ # Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example,
90
+ # when using +find+ method)
91
+ # does not match number of expected variables.
92
+ #
93
+ # For example, in
94
+ #
95
+ # Location.where("lat = ? AND lng = ?", 53.7362)
96
+ #
97
+ # two placeholders are given but only one variable to fill them.
98
+ class PreparedStatementInvalid < ActiveRecordError
99
+ end
100
+
101
+ # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
102
+ # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
103
+ # the page before the other.
104
+ #
105
+ # Read more about optimistic locking in ActiveRecord::Locking module RDoc.
106
+ class StaleObjectError < ActiveRecordError
107
+ attr_reader :record, :attempted_action
108
+
109
+ def initialize(record, attempted_action)
110
+ super("Attempted to #{attempted_action} a stale object: #{record.class.name}")
111
+ @record = record
112
+ @attempted_action = attempted_action
113
+ end
114
+
115
+ end
116
+
117
+ # Raised when association is being configured improperly or
118
+ # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
119
+ class ConfigurationError < ActiveRecordError
120
+ end
121
+
122
+ # Raised on attempt to update record that is instantiated as read only.
123
+ class ReadOnlyRecord < ActiveRecordError
124
+ end
125
+
126
+ # ActiveRecord::Transactions::ClassMethods.transaction uses this exception
127
+ # to distinguish a deliberate rollback from other exceptional situations.
128
+ # Normally, raising an exception will cause the +transaction+ method to rollback
129
+ # the database transaction *and* pass on the exception. But if you raise an
130
+ # ActiveRecord::Rollback exception, then the database transaction will be rolled back,
131
+ # without passing on the exception.
132
+ #
133
+ # For example, you could do this in your controller to rollback a transaction:
134
+ #
135
+ # class BooksController < ActionController::Base
136
+ # def create
137
+ # Book.transaction do
138
+ # book = Book.new(params[:book])
139
+ # book.save!
140
+ # if today_is_friday?
141
+ # # The system must fail on Friday so that our support department
142
+ # # won't be out of job. We silently rollback this transaction
143
+ # # without telling the user.
144
+ # raise ActiveRecord::Rollback, "Call tech support!"
145
+ # end
146
+ # end
147
+ # # ActiveRecord::Rollback is the only exception that won't be passed on
148
+ # # by ActiveRecord::Base.transaction, so this line will still be reached
149
+ # # even on Friday.
150
+ # redirect_to root_url
151
+ # end
152
+ # end
153
+ class Rollback < ActiveRecordError
154
+ end
155
+
156
+ # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
157
+ class DangerousAttributeError < ActiveRecordError
158
+ end
159
+
160
+ # Raised when unknown attributes are supplied via mass assignment.
161
+ class UnknownAttributeError < NoMethodError
162
+ end
163
+
164
+ # Raised when an error occurred while doing a mass assignment to an attribute through the
165
+ # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
166
+ # offending attribute.
167
+ class AttributeAssignmentError < ActiveRecordError
168
+ attr_reader :exception, :attribute
169
+ def initialize(message, exception, attribute)
170
+ super(message)
171
+ @exception = exception
172
+ @attribute = attribute
173
+ end
174
+ end
175
+
176
+ # Raised when there are multiple errors while doing a mass assignment through the +attributes+
177
+ # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
178
+ # objects, each corresponding to the error while assigning to an attribute.
179
+ class MultiparameterAssignmentErrors < ActiveRecordError
180
+ attr_reader :errors
181
+ def initialize(errors)
182
+ @errors = errors
183
+ end
184
+ end
185
+
186
+ # Raised when a primary key is needed, but there is not one specified in the schema or model.
187
+ class UnknownPrimaryKey < ActiveRecordError
188
+ attr_reader :model
189
+
190
+ def initialize(model)
191
+ super("Unknown primary key for table #{model.table_name} in model #{model}.")
192
+ @model = model
193
+ end
194
+
195
+ end
196
+
197
+ # Raised when a relation cannot be mutated because it's already loaded.
198
+ #
199
+ # class Task < ActiveRecord::Base
200
+ # end
201
+ #
202
+ # relation = Task.all
203
+ # relation.loaded? # => true
204
+ #
205
+ # # Methods which try to mutate a loaded relation fail.
206
+ # relation.where!(title: 'TODO') # => ActiveRecord::ImmutableRelation
207
+ # relation.limit!(5) # => ActiveRecord::ImmutableRelation
208
+ class ImmutableRelation < ActiveRecordError
209
+ end
210
+
211
+ class TransactionIsolationError < ActiveRecordError
212
+ end
213
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_support/lazy_load_hooks'
2
+ require 'active_record/explain_registry'
3
+
4
+ module ActiveRecord
5
+ module Explain
6
+ # Executes the block with the collect flag enabled. Queries are collected
7
+ # asynchronously by the subscriber and returned.
8
+ def collecting_queries_for_explain # :nodoc:
9
+ ExplainRegistry.collect = true
10
+ yield
11
+ ExplainRegistry.queries
12
+ ensure
13
+ ExplainRegistry.reset
14
+ end
15
+
16
+ # Makes the adapter execute EXPLAIN for the tuples of queries and bindings.
17
+ # Returns a formatted string ready to be logged.
18
+ def exec_explain(queries) # :nodoc:
19
+ str = queries.map do |sql, bind|
20
+ [].tap do |msg|
21
+ msg << "EXPLAIN for: #{sql}"
22
+ unless bind.empty?
23
+ bind_msg = bind.map {|col, val| [col.name, val]}.inspect
24
+ msg.last << " #{bind_msg}"
25
+ end
26
+ msg << connection.explain(sql, bind)
27
+ end.join("\n")
28
+ end.join("\n")
29
+
30
+ # Overriding inspect to be more human readable, specially in the console.
31
+ def str.inspect
32
+ self
33
+ end
34
+
35
+ str
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_support/per_thread_registry'
2
+
3
+ module ActiveRecord
4
+ # This is a thread locals registry for EXPLAIN. For example
5
+ #
6
+ # ActiveRecord::ExplainRegistry.queries
7
+ #
8
+ # returns the collected queries local to the current thread.
9
+ #
10
+ # See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
11
+ # for further details.
12
+ class ExplainRegistry # :nodoc:
13
+ extend ActiveSupport::PerThreadRegistry
14
+
15
+ attr_accessor :queries, :collect
16
+
17
+ def initialize
18
+ reset
19
+ end
20
+
21
+ def collect?
22
+ @collect
23
+ end
24
+
25
+ def reset
26
+ @collect = false
27
+ @queries = []
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ require 'active_support/notifications'
2
+ require 'active_record/explain_registry'
3
+
4
+ module ActiveRecord
5
+ class ExplainSubscriber # :nodoc:
6
+ def start(name, id, payload)
7
+ # unused
8
+ end
9
+
10
+ def finish(name, id, payload)
11
+ if ExplainRegistry.collect? && !ignore_payload?(payload)
12
+ ExplainRegistry.queries << payload.values_at(:sql, :binds)
13
+ end
14
+ end
15
+
16
+ # SCHEMA queries cannot be EXPLAINed, also we do not want to run EXPLAIN on
17
+ # our own EXPLAINs now matter how loopingly beautiful that would be.
18
+ #
19
+ # On the other hand, we want to monitor the performance of our real database
20
+ # queries, not the performance of the access to the query cache.
21
+ IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN CACHE)
22
+ EXPLAINED_SQLS = /\A\s*(select|update|delete|insert)\b/i
23
+ def ignore_payload?(payload)
24
+ payload[:exception] || IGNORED_PAYLOADS.include?(payload[:name]) || payload[:sql] !~ EXPLAINED_SQLS
25
+ end
26
+
27
+ ActiveSupport::Notifications.subscribe("sql.active_record", new)
28
+ end
29
+ end
@@ -0,0 +1,55 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+
4
+ module ActiveRecord
5
+ class FixtureSet
6
+ class File # :nodoc:
7
+ include Enumerable
8
+
9
+ ##
10
+ # Open a fixture file named +file+. When called with a block, the block
11
+ # is called with the filehandle and the filehandle is automatically closed
12
+ # when the block finishes.
13
+ def self.open(file)
14
+ x = new file
15
+ block_given? ? yield(x) : x
16
+ end
17
+
18
+ def initialize(file)
19
+ @file = file
20
+ @rows = nil
21
+ end
22
+
23
+ def each(&block)
24
+ rows.each(&block)
25
+ end
26
+
27
+
28
+ private
29
+ def rows
30
+ return @rows if @rows
31
+
32
+ begin
33
+ data = YAML.load(render(IO.read(@file)))
34
+ rescue ArgumentError, Psych::SyntaxError => error
35
+ raise Fixture::FormatError, "a YAML error occurred parsing #{@file}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}", error.backtrace
36
+ end
37
+ @rows = data ? validate(data).to_a : []
38
+ end
39
+
40
+ def render(content)
41
+ ERB.new(content).result
42
+ end
43
+
44
+ # Validate our unmarshalled data.
45
+ def validate(data)
46
+ unless Hash === data || YAML::Omap === data
47
+ raise Fixture::FormatError, 'fixture is not a hash'
48
+ end
49
+
50
+ raise Fixture::FormatError unless data.all? { |name, row| Hash === row }
51
+ data
52
+ end
53
+ end
54
+ end
55
+ end