activerecord 4.2.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 (221) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1372 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +218 -0
  5. data/examples/performance.rb +184 -0
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record.rb +173 -0
  8. data/lib/active_record/aggregations.rb +266 -0
  9. data/lib/active_record/association_relation.rb +22 -0
  10. data/lib/active_record/associations.rb +1724 -0
  11. data/lib/active_record/associations/alias_tracker.rb +87 -0
  12. data/lib/active_record/associations/association.rb +253 -0
  13. data/lib/active_record/associations/association_scope.rb +194 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +111 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
  16. data/lib/active_record/associations/builder/association.rb +149 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +116 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +91 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +124 -0
  20. data/lib/active_record/associations/builder/has_many.rb +15 -0
  21. data/lib/active_record/associations/builder/has_one.rb +23 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +38 -0
  23. data/lib/active_record/associations/collection_association.rb +634 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1027 -0
  25. data/lib/active_record/associations/has_many_association.rb +184 -0
  26. data/lib/active_record/associations/has_many_through_association.rb +238 -0
  27. data/lib/active_record/associations/has_one_association.rb +105 -0
  28. data/lib/active_record/associations/has_one_through_association.rb +36 -0
  29. data/lib/active_record/associations/join_dependency.rb +282 -0
  30. data/lib/active_record/associations/join_dependency/join_association.rb +122 -0
  31. data/lib/active_record/associations/join_dependency/join_base.rb +22 -0
  32. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  33. data/lib/active_record/associations/preloader.rb +203 -0
  34. data/lib/active_record/associations/preloader/association.rb +162 -0
  35. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  36. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  37. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  38. data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
  39. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  40. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  41. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  42. data/lib/active_record/associations/preloader/through_association.rb +96 -0
  43. data/lib/active_record/associations/singular_association.rb +86 -0
  44. data/lib/active_record/associations/through_association.rb +96 -0
  45. data/lib/active_record/attribute.rb +149 -0
  46. data/lib/active_record/attribute_assignment.rb +212 -0
  47. data/lib/active_record/attribute_decorators.rb +66 -0
  48. data/lib/active_record/attribute_methods.rb +439 -0
  49. data/lib/active_record/attribute_methods/before_type_cast.rb +71 -0
  50. data/lib/active_record/attribute_methods/dirty.rb +181 -0
  51. data/lib/active_record/attribute_methods/primary_key.rb +128 -0
  52. data/lib/active_record/attribute_methods/query.rb +40 -0
  53. data/lib/active_record/attribute_methods/read.rb +103 -0
  54. data/lib/active_record/attribute_methods/serialization.rb +70 -0
  55. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
  56. data/lib/active_record/attribute_methods/write.rb +83 -0
  57. data/lib/active_record/attribute_set.rb +77 -0
  58. data/lib/active_record/attribute_set/builder.rb +86 -0
  59. data/lib/active_record/attributes.rb +139 -0
  60. data/lib/active_record/autosave_association.rb +439 -0
  61. data/lib/active_record/base.rb +317 -0
  62. data/lib/active_record/callbacks.rb +313 -0
  63. data/lib/active_record/coders/json.rb +13 -0
  64. data/lib/active_record/coders/yaml_column.rb +38 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +659 -0
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +67 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +373 -0
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -0
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +133 -0
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +574 -0
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +991 -0
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +219 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -0
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +883 -0
  78. data/lib/active_record/connection_adapters/column.rb +82 -0
  79. data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +282 -0
  81. data/lib/active_record/connection_adapters/mysql_adapter.rb +491 -0
  82. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +99 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +97 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  111. data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
  112. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +588 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +754 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +628 -0
  119. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  120. data/lib/active_record/connection_handling.rb +132 -0
  121. data/lib/active_record/core.rb +566 -0
  122. data/lib/active_record/counter_cache.rb +175 -0
  123. data/lib/active_record/dynamic_matchers.rb +140 -0
  124. data/lib/active_record/enum.rb +198 -0
  125. data/lib/active_record/errors.rb +252 -0
  126. data/lib/active_record/explain.rb +38 -0
  127. data/lib/active_record/explain_registry.rb +30 -0
  128. data/lib/active_record/explain_subscriber.rb +29 -0
  129. data/lib/active_record/fixture_set/file.rb +56 -0
  130. data/lib/active_record/fixtures.rb +1007 -0
  131. data/lib/active_record/gem_version.rb +15 -0
  132. data/lib/active_record/inheritance.rb +247 -0
  133. data/lib/active_record/integration.rb +113 -0
  134. data/lib/active_record/locale/en.yml +47 -0
  135. data/lib/active_record/locking/optimistic.rb +204 -0
  136. data/lib/active_record/locking/pessimistic.rb +77 -0
  137. data/lib/active_record/log_subscriber.rb +75 -0
  138. data/lib/active_record/migration.rb +1051 -0
  139. data/lib/active_record/migration/command_recorder.rb +197 -0
  140. data/lib/active_record/migration/join_table.rb +15 -0
  141. data/lib/active_record/model_schema.rb +340 -0
  142. data/lib/active_record/nested_attributes.rb +548 -0
  143. data/lib/active_record/no_touching.rb +52 -0
  144. data/lib/active_record/null_relation.rb +81 -0
  145. data/lib/active_record/persistence.rb +532 -0
  146. data/lib/active_record/query_cache.rb +56 -0
  147. data/lib/active_record/querying.rb +68 -0
  148. data/lib/active_record/railtie.rb +162 -0
  149. data/lib/active_record/railties/console_sandbox.rb +5 -0
  150. data/lib/active_record/railties/controller_runtime.rb +50 -0
  151. data/lib/active_record/railties/databases.rake +391 -0
  152. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  153. data/lib/active_record/readonly_attributes.rb +23 -0
  154. data/lib/active_record/reflection.rb +881 -0
  155. data/lib/active_record/relation.rb +681 -0
  156. data/lib/active_record/relation/batches.rb +138 -0
  157. data/lib/active_record/relation/calculations.rb +403 -0
  158. data/lib/active_record/relation/delegation.rb +140 -0
  159. data/lib/active_record/relation/finder_methods.rb +528 -0
  160. data/lib/active_record/relation/merger.rb +170 -0
  161. data/lib/active_record/relation/predicate_builder.rb +126 -0
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +47 -0
  163. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  164. data/lib/active_record/relation/query_methods.rb +1176 -0
  165. data/lib/active_record/relation/spawn_methods.rb +75 -0
  166. data/lib/active_record/result.rb +131 -0
  167. data/lib/active_record/runtime_registry.rb +22 -0
  168. data/lib/active_record/sanitization.rb +191 -0
  169. data/lib/active_record/schema.rb +64 -0
  170. data/lib/active_record/schema_dumper.rb +251 -0
  171. data/lib/active_record/schema_migration.rb +56 -0
  172. data/lib/active_record/scoping.rb +87 -0
  173. data/lib/active_record/scoping/default.rb +134 -0
  174. data/lib/active_record/scoping/named.rb +164 -0
  175. data/lib/active_record/serialization.rb +22 -0
  176. data/lib/active_record/serializers/xml_serializer.rb +193 -0
  177. data/lib/active_record/statement_cache.rb +111 -0
  178. data/lib/active_record/store.rb +205 -0
  179. data/lib/active_record/tasks/database_tasks.rb +296 -0
  180. data/lib/active_record/tasks/mysql_database_tasks.rb +145 -0
  181. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  182. data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
  183. data/lib/active_record/timestamp.rb +121 -0
  184. data/lib/active_record/transactions.rb +417 -0
  185. data/lib/active_record/translation.rb +22 -0
  186. data/lib/active_record/type.rb +23 -0
  187. data/lib/active_record/type/big_integer.rb +13 -0
  188. data/lib/active_record/type/binary.rb +50 -0
  189. data/lib/active_record/type/boolean.rb +30 -0
  190. data/lib/active_record/type/date.rb +46 -0
  191. data/lib/active_record/type/date_time.rb +43 -0
  192. data/lib/active_record/type/decimal.rb +40 -0
  193. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  194. data/lib/active_record/type/decorator.rb +14 -0
  195. data/lib/active_record/type/float.rb +19 -0
  196. data/lib/active_record/type/hash_lookup_type_map.rb +17 -0
  197. data/lib/active_record/type/integer.rb +55 -0
  198. data/lib/active_record/type/mutable.rb +16 -0
  199. data/lib/active_record/type/numeric.rb +36 -0
  200. data/lib/active_record/type/serialized.rb +56 -0
  201. data/lib/active_record/type/string.rb +36 -0
  202. data/lib/active_record/type/text.rb +11 -0
  203. data/lib/active_record/type/time.rb +26 -0
  204. data/lib/active_record/type/time_value.rb +38 -0
  205. data/lib/active_record/type/type_map.rb +64 -0
  206. data/lib/active_record/type/unsigned_integer.rb +15 -0
  207. data/lib/active_record/type/value.rb +101 -0
  208. data/lib/active_record/validations.rb +90 -0
  209. data/lib/active_record/validations/associated.rb +51 -0
  210. data/lib/active_record/validations/presence.rb +67 -0
  211. data/lib/active_record/validations/uniqueness.rb +229 -0
  212. data/lib/active_record/version.rb +8 -0
  213. data/lib/rails/generators/active_record.rb +17 -0
  214. data/lib/rails/generators/active_record/migration.rb +18 -0
  215. data/lib/rails/generators/active_record/migration/migration_generator.rb +70 -0
  216. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +22 -0
  217. data/lib/rails/generators/active_record/migration/templates/migration.rb +45 -0
  218. data/lib/rails/generators/active_record/model/model_generator.rb +52 -0
  219. data/lib/rails/generators/active_record/model/templates/model.rb +10 -0
  220. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  221. metadata +309 -0
@@ -0,0 +1,56 @@
1
+ module ActiveRecord
2
+ # = Active Record Query Cache
3
+ class QueryCache
4
+ module ClassMethods
5
+ # Enable the query cache within the block if Active Record is configured.
6
+ # If it's not, it will execute the given block.
7
+ def cache(&block)
8
+ if ActiveRecord::Base.connected?
9
+ connection.cache(&block)
10
+ else
11
+ yield
12
+ end
13
+ end
14
+
15
+ # Disable the query cache within the block if Active Record is configured.
16
+ # If it's not, it will execute the given block.
17
+ def uncached(&block)
18
+ if ActiveRecord::Base.connected?
19
+ connection.uncached(&block)
20
+ else
21
+ yield
22
+ end
23
+ end
24
+ end
25
+
26
+ def initialize(app)
27
+ @app = app
28
+ end
29
+
30
+ def call(env)
31
+ connection = ActiveRecord::Base.connection
32
+ enabled = connection.query_cache_enabled
33
+ connection_id = ActiveRecord::Base.connection_id
34
+ connection.enable_query_cache!
35
+
36
+ response = @app.call(env)
37
+ response[2] = Rack::BodyProxy.new(response[2]) do
38
+ restore_query_cache_settings(connection_id, enabled)
39
+ end
40
+
41
+ response
42
+ rescue Exception => e
43
+ restore_query_cache_settings(connection_id, enabled)
44
+ raise e
45
+ end
46
+
47
+ private
48
+
49
+ def restore_query_cache_settings(connection_id, enabled)
50
+ ActiveRecord::Base.connection_id = connection_id
51
+ ActiveRecord::Base.connection.clear_query_cache
52
+ ActiveRecord::Base.connection.disable_query_cache! unless enabled
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,68 @@
1
+ module ActiveRecord
2
+ module Querying
3
+ delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, to: :all
4
+ delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, to: :all
5
+ delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
6
+ delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
7
+ delegate :find_by, :find_by!, to: :all
8
+ delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
9
+ delegate :find_each, :find_in_batches, to: :all
10
+ delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins,
11
+ :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
12
+ :having, :create_with, :uniq, :distinct, :references, :none, :unscope, to: :all
13
+ delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
14
+ delegate :pluck, :ids, to: :all
15
+
16
+ # Executes a custom SQL query against your database and returns all the results. The results will
17
+ # be returned as an array with columns requested encapsulated as attributes of the model you call
18
+ # this method from. If you call <tt>Product.find_by_sql</tt> then the results will be returned in
19
+ # a +Product+ object with the attributes you specified in the SQL query.
20
+ #
21
+ # If you call a complicated SQL query which spans multiple tables the columns specified by the
22
+ # SELECT will be attributes of the model, whether or not they are columns of the corresponding
23
+ # table.
24
+ #
25
+ # The +sql+ parameter is a full SQL query as a string. It will be called as is, there will be
26
+ # no database agnostic conversions performed. This should be a last resort because using, for example,
27
+ # MySQL specific terms will lock you to using that particular database engine or require you to
28
+ # change your call if you switch engines.
29
+ #
30
+ # # A simple SQL query spanning multiple tables
31
+ # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
32
+ # # => [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
33
+ #
34
+ # You can use the same string replacement techniques as you can with <tt>ActiveRecord::QueryMethods#where</tt>:
35
+ #
36
+ # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
37
+ # Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
38
+ def find_by_sql(sql, binds = [])
39
+ result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds)
40
+ column_types = result_set.column_types.dup
41
+ columns_hash.each_key { |k| column_types.delete k }
42
+ message_bus = ActiveSupport::Notifications.instrumenter
43
+
44
+ payload = {
45
+ record_count: result_set.length,
46
+ class_name: name
47
+ }
48
+
49
+ message_bus.instrument('instantiation.active_record', payload) do
50
+ result_set.map { |record| instantiate(record, column_types) }
51
+ end
52
+ end
53
+
54
+ # Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
55
+ # The use of this method should be restricted to complicated SQL queries that can't be executed
56
+ # using the ActiveRecord::Calculations class methods. Look into those before using this.
57
+ #
58
+ # ==== Parameters
59
+ #
60
+ # * +sql+ - An SQL statement which should return a count query from the database, see the example below.
61
+ #
62
+ # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
63
+ def count_by_sql(sql)
64
+ sql = sanitize_conditions(sql)
65
+ connection.select_value(sql, "#{name} Count").to_i
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,162 @@
1
+ require "active_record"
2
+ require "rails"
3
+ require "active_model/railtie"
4
+
5
+ # For now, action_controller must always be present with
6
+ # rails, so let's make sure that it gets required before
7
+ # here. This is needed for correctly setting up the middleware.
8
+ # In the future, this might become an optional require.
9
+ require "action_controller/railtie"
10
+
11
+ module ActiveRecord
12
+ # = Active Record Railtie
13
+ class Railtie < Rails::Railtie # :nodoc:
14
+ config.active_record = ActiveSupport::OrderedOptions.new
15
+
16
+ config.app_generators.orm :active_record, :migration => true,
17
+ :timestamps => true
18
+
19
+ config.app_middleware.insert_after "::ActionDispatch::Callbacks",
20
+ "ActiveRecord::QueryCache"
21
+
22
+ config.app_middleware.insert_after "::ActionDispatch::Callbacks",
23
+ "ActiveRecord::ConnectionAdapters::ConnectionManagement"
24
+
25
+ config.action_dispatch.rescue_responses.merge!(
26
+ 'ActiveRecord::RecordNotFound' => :not_found,
27
+ 'ActiveRecord::StaleObjectError' => :conflict,
28
+ 'ActiveRecord::RecordInvalid' => :unprocessable_entity,
29
+ 'ActiveRecord::RecordNotSaved' => :unprocessable_entity
30
+ )
31
+
32
+
33
+ config.active_record.use_schema_cache_dump = true
34
+ config.active_record.maintain_test_schema = true
35
+
36
+ config.eager_load_namespaces << ActiveRecord
37
+
38
+ rake_tasks do
39
+ namespace :db do
40
+ task :load_config do
41
+ ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration
42
+
43
+ if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
44
+ if engine.paths['db/migrate'].existent
45
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths += engine.paths['db/migrate'].to_a
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ load "active_record/railties/databases.rake"
52
+ end
53
+
54
+ # When loading console, force ActiveRecord::Base to be loaded
55
+ # to avoid cross references when loading a constant for the
56
+ # first time. Also, make it output to STDERR.
57
+ console do |app|
58
+ require "active_record/railties/console_sandbox" if app.sandbox?
59
+ require "active_record/base"
60
+ console = ActiveSupport::Logger.new(STDERR)
61
+ Rails.logger.extend ActiveSupport::Logger.broadcast console
62
+ end
63
+
64
+ runner do
65
+ require "active_record/base"
66
+ end
67
+
68
+ initializer "active_record.initialize_timezone" do
69
+ ActiveSupport.on_load(:active_record) do
70
+ self.time_zone_aware_attributes = true
71
+ self.default_timezone = :utc
72
+ end
73
+ end
74
+
75
+ initializer "active_record.logger" do
76
+ ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger }
77
+ end
78
+
79
+ initializer "active_record.migration_error" do
80
+ if config.active_record.delete(:migration_error) == :page_load
81
+ config.app_middleware.insert_after "::ActionDispatch::Callbacks",
82
+ "ActiveRecord::Migration::CheckPending"
83
+ end
84
+ end
85
+
86
+ initializer "active_record.check_schema_cache_dump" do
87
+ if config.active_record.delete(:use_schema_cache_dump)
88
+ config.after_initialize do |app|
89
+ ActiveSupport.on_load(:active_record) do
90
+ filename = File.join(app.config.paths["db"].first, "schema_cache.dump")
91
+
92
+ if File.file?(filename)
93
+ cache = Marshal.load File.binread filename
94
+ if cache.version == ActiveRecord::Migrator.current_version
95
+ self.connection.schema_cache = cache
96
+ else
97
+ warn "Ignoring db/schema_cache.dump because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ initializer "active_record.set_configs" do |app|
106
+ ActiveSupport.on_load(:active_record) do
107
+ app.config.active_record.each do |k,v|
108
+ send "#{k}=", v
109
+ end
110
+ end
111
+ end
112
+
113
+ # This sets the database configuration from Configuration#database_configuration
114
+ # and then establishes the connection.
115
+ initializer "active_record.initialize_database" do |app|
116
+ ActiveSupport.on_load(:active_record) do
117
+ self.configurations = Rails.application.config.database_configuration
118
+
119
+ begin
120
+ establish_connection
121
+ rescue ActiveRecord::NoDatabaseError
122
+ warn <<-end_warning
123
+ Oops - You have a database configured, but it doesn't exist yet!
124
+
125
+ Here's how to get started:
126
+
127
+ 1. Configure your database in config/database.yml.
128
+ 2. Run `bin/rake db:create` to create the database.
129
+ 3. Run `bin/rake db:setup` to load your database schema.
130
+ end_warning
131
+ raise
132
+ end
133
+ end
134
+ end
135
+
136
+ # Expose database runtime to controller for logging.
137
+ initializer "active_record.log_runtime" do
138
+ require "active_record/railties/controller_runtime"
139
+ ActiveSupport.on_load(:action_controller) do
140
+ include ActiveRecord::Railties::ControllerRuntime
141
+ end
142
+ end
143
+
144
+ initializer "active_record.set_reloader_hooks" do |app|
145
+ hook = app.config.reload_classes_only_on_change ? :to_prepare : :to_cleanup
146
+
147
+ ActiveSupport.on_load(:active_record) do
148
+ ActionDispatch::Reloader.send(hook) do
149
+ if ActiveRecord::Base.connected?
150
+ ActiveRecord::Base.clear_reloadable_connections!
151
+ ActiveRecord::Base.clear_cache!
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ initializer "active_record.add_watchable_files" do |app|
158
+ path = app.paths["db"].first
159
+ config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,5 @@
1
+ ActiveRecord::Base.connection.begin_transaction(joinable: false)
2
+
3
+ at_exit do
4
+ ActiveRecord::Base.connection.rollback_transaction
5
+ end
@@ -0,0 +1,50 @@
1
+ require 'active_support/core_ext/module/attr_internal'
2
+ require 'active_record/log_subscriber'
3
+
4
+ module ActiveRecord
5
+ module Railties # :nodoc:
6
+ module ControllerRuntime #:nodoc:
7
+ extend ActiveSupport::Concern
8
+
9
+ protected
10
+
11
+ attr_internal :db_runtime
12
+
13
+ def process_action(action, *args)
14
+ # We also need to reset the runtime before each action
15
+ # because of queries in middleware or in cases we are streaming
16
+ # and it won't be cleaned up by the method below.
17
+ ActiveRecord::LogSubscriber.reset_runtime
18
+ super
19
+ end
20
+
21
+ def cleanup_view_runtime
22
+ if ActiveRecord::Base.connected?
23
+ db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
24
+ self.db_runtime = (db_runtime || 0) + db_rt_before_render
25
+ runtime = super
26
+ db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime
27
+ self.db_runtime += db_rt_after_render
28
+ runtime - db_rt_after_render
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ def append_info_to_payload(payload)
35
+ super
36
+ if ActiveRecord::Base.connected?
37
+ payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
38
+ end
39
+ end
40
+
41
+ module ClassMethods # :nodoc:
42
+ def log_process_action(payload)
43
+ messages, db_runtime = super, payload[:db_runtime]
44
+ messages << ("ActiveRecord: %.1fms" % db_runtime.to_f) if db_runtime
45
+ messages
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,391 @@
1
+ require 'active_record'
2
+
3
+ db_namespace = namespace :db do
4
+ task :load_config do
5
+ ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
6
+ ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
7
+ end
8
+
9
+ namespace :create do
10
+ task :all => :load_config do
11
+ ActiveRecord::Tasks::DatabaseTasks.create_all
12
+ end
13
+ end
14
+
15
+ desc 'Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV it defaults to creating the development and test databases.'
16
+ task :create => [:load_config] do
17
+ ActiveRecord::Tasks::DatabaseTasks.create_current
18
+ end
19
+
20
+ namespace :drop do
21
+ task :all => :load_config do
22
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
23
+ end
24
+ end
25
+
26
+ desc 'Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to dropping the development and test databases.'
27
+ task :drop => [:load_config] do
28
+ ActiveRecord::Tasks::DatabaseTasks.drop_current
29
+ end
30
+
31
+ namespace :purge do
32
+ task :all => :load_config do
33
+ ActiveRecord::Tasks::DatabaseTasks.purge_all
34
+ end
35
+ end
36
+
37
+ # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
38
+ task :purge => [:load_config] do
39
+ ActiveRecord::Tasks::DatabaseTasks.purge_current
40
+ end
41
+
42
+ desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
43
+ task :migrate => [:environment, :load_config] do
44
+ ActiveRecord::Tasks::DatabaseTasks.migrate
45
+ db_namespace['_dump'].invoke if ActiveRecord::Base.dump_schema_after_migration
46
+ end
47
+
48
+ task :_dump do
49
+ case ActiveRecord::Base.schema_format
50
+ when :ruby then db_namespace["schema:dump"].invoke
51
+ when :sql then db_namespace["structure:dump"].invoke
52
+ else
53
+ raise "unknown schema format #{ActiveRecord::Base.schema_format}"
54
+ end
55
+ # Allow this task to be called as many times as required. An example is the
56
+ # migrate:redo task, which calls other two internally that depend on this one.
57
+ db_namespace['_dump'].reenable
58
+ end
59
+
60
+ namespace :migrate do
61
+ # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
62
+ task :redo => [:environment, :load_config] do
63
+ if ENV['VERSION']
64
+ db_namespace['migrate:down'].invoke
65
+ db_namespace['migrate:up'].invoke
66
+ else
67
+ db_namespace['rollback'].invoke
68
+ db_namespace['migrate'].invoke
69
+ end
70
+ end
71
+
72
+ # desc 'Resets your database using your migrations for the current environment'
73
+ task :reset => ['db:drop', 'db:create', 'db:migrate']
74
+
75
+ # desc 'Runs the "up" for a given migration VERSION.'
76
+ task :up => [:environment, :load_config] do
77
+ version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
78
+ raise 'VERSION is required' unless version
79
+ ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, version)
80
+ db_namespace['_dump'].invoke
81
+ end
82
+
83
+ # desc 'Runs the "down" for a given migration VERSION.'
84
+ task :down => [:environment, :load_config] do
85
+ version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
86
+ raise 'VERSION is required - To go down one migration, run db:rollback' unless version
87
+ ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version)
88
+ db_namespace['_dump'].invoke
89
+ end
90
+
91
+ desc 'Display status of migrations'
92
+ task :status => [:environment, :load_config] do
93
+ unless ActiveRecord::SchemaMigration.table_exists?
94
+ abort 'Schema migrations table does not exist yet.'
95
+ end
96
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
97
+
98
+ file_list =
99
+ ActiveRecord::Migrator.migrations_paths.flat_map do |path|
100
+ # match "20091231235959_some_name.rb" and "001_some_name.rb" pattern
101
+ Dir.foreach(path).grep(/^(\d{3,})_(.+)\.rb$/) do
102
+ version = ActiveRecord::SchemaMigration.normalize_migration_number($1)
103
+ status = db_list.delete(version) ? 'up' : 'down'
104
+ [status, version, $2.humanize]
105
+ end
106
+ end
107
+
108
+ db_list.map! do |version|
109
+ ['up', version, '********** NO FILE **********']
110
+ end
111
+ # output
112
+ puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
113
+ puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
114
+ puts "-" * 50
115
+ (db_list + file_list).sort_by { |_, version, _| version }.each do |status, version, name|
116
+ puts "#{status.center(8)} #{version.ljust(14)} #{name}"
117
+ end
118
+ puts
119
+ end
120
+ end
121
+
122
+ desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
123
+ task :rollback => [:environment, :load_config] do
124
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
125
+ ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step)
126
+ db_namespace['_dump'].invoke
127
+ end
128
+
129
+ # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
130
+ task :forward => [:environment, :load_config] do
131
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
132
+ ActiveRecord::Migrator.forward(ActiveRecord::Migrator.migrations_paths, step)
133
+ db_namespace['_dump'].invoke
134
+ end
135
+
136
+ # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
137
+ task :reset => [:environment, :load_config] do
138
+ db_namespace["drop"].invoke
139
+ db_namespace["setup"].invoke
140
+ end
141
+
142
+ # desc "Retrieves the charset for the current environment's database"
143
+ task :charset => [:environment, :load_config] do
144
+ puts ActiveRecord::Tasks::DatabaseTasks.charset_current
145
+ end
146
+
147
+ # desc "Retrieves the collation for the current environment's database"
148
+ task :collation => [:environment, :load_config] do
149
+ begin
150
+ puts ActiveRecord::Tasks::DatabaseTasks.collation_current
151
+ rescue NoMethodError
152
+ $stderr.puts 'Sorry, your database adapter is not supported yet. Feel free to submit a patch.'
153
+ end
154
+ end
155
+
156
+ desc 'Retrieves the current schema version number'
157
+ task :version => [:environment, :load_config] do
158
+ puts "Current version: #{ActiveRecord::Migrator.current_version}"
159
+ end
160
+
161
+ # desc "Raises an error if there are pending migrations"
162
+ task :abort_if_pending_migrations => :environment do
163
+ pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Migrator.migrations_paths).pending_migrations
164
+
165
+ if pending_migrations.any?
166
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
167
+ pending_migrations.each do |pending_migration|
168
+ puts ' %4d %s' % [pending_migration.version, pending_migration.name]
169
+ end
170
+ abort %{Run `rake db:migrate` to update your database then try again.}
171
+ end
172
+ end
173
+
174
+ desc 'Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the database first)'
175
+ task :setup => ['db:schema:load_if_ruby', 'db:structure:load_if_sql', :seed]
176
+
177
+ desc 'Load the seed data from db/seeds.rb'
178
+ task :seed do
179
+ db_namespace['abort_if_pending_migrations'].invoke
180
+ ActiveRecord::Tasks::DatabaseTasks.load_seed
181
+ end
182
+
183
+ namespace :fixtures do
184
+ desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
185
+ task :load => [:environment, :load_config] do
186
+ require 'active_record/fixtures'
187
+
188
+ base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
189
+
190
+ fixtures_dir = if ENV['FIXTURES_DIR']
191
+ File.join base_dir, ENV['FIXTURES_DIR']
192
+ else
193
+ base_dir
194
+ end
195
+
196
+ fixture_files = if ENV['FIXTURES']
197
+ ENV['FIXTURES'].split(',')
198
+ else
199
+ # The use of String#[] here is to support namespaced fixtures
200
+ Dir["#{fixtures_dir}/**/*.yml"].map {|f| f[(fixtures_dir.size + 1)..-5] }
201
+ end
202
+
203
+ ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
204
+ end
205
+
206
+ # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
207
+ task :identify => [:environment, :load_config] do
208
+ require 'active_record/fixtures'
209
+
210
+ label, id = ENV['LABEL'], ENV['ID']
211
+ raise 'LABEL or ID required' if label.blank? && id.blank?
212
+
213
+ puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::FixtureSet.identify(label)}.) if label
214
+
215
+ base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
216
+
217
+ Dir["#{base_dir}/**/*.yml"].each do |file|
218
+ if data = YAML::load(ERB.new(IO.read(file)).result)
219
+ data.each_key do |key|
220
+ key_id = ActiveRecord::FixtureSet.identify(key)
221
+
222
+ if key == label || key_id == id.to_i
223
+ puts "#{file}: #{key} (#{key_id})"
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ namespace :schema do
232
+ desc 'Create a db/schema.rb file that is portable against any DB supported by AR'
233
+ task :dump => [:environment, :load_config] do
234
+ require 'active_record/schema_dumper'
235
+ filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
236
+ File.open(filename, "w:utf-8") do |file|
237
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
238
+ end
239
+ db_namespace['schema:dump'].reenable
240
+ end
241
+
242
+ desc 'Load a schema.rb file into the database'
243
+ task :load => [:environment, :load_config] do
244
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA'])
245
+ end
246
+
247
+ task :load_if_ruby => ['db:create', :environment] do
248
+ db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
249
+ end
250
+
251
+ namespace :cache do
252
+ desc 'Create a db/schema_cache.dump file.'
253
+ task :dump => [:environment, :load_config] do
254
+ con = ActiveRecord::Base.connection
255
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
256
+
257
+ con.schema_cache.clear!
258
+ con.tables.each { |table| con.schema_cache.add(table) }
259
+ open(filename, 'wb') { |f| f.write(Marshal.dump(con.schema_cache)) }
260
+ end
261
+
262
+ desc 'Clear a db/schema_cache.dump file.'
263
+ task :clear => [:environment, :load_config] do
264
+ filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
265
+ FileUtils.rm(filename) if File.exist?(filename)
266
+ end
267
+ end
268
+
269
+ end
270
+
271
+ namespace :structure do
272
+ desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql'
273
+ task :dump => [:environment, :load_config] do
274
+ filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
275
+ current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
276
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
277
+
278
+ if ActiveRecord::Base.connection.supports_migrations? &&
279
+ ActiveRecord::SchemaMigration.table_exists?
280
+ File.open(filename, "a") do |f|
281
+ f.puts ActiveRecord::Base.connection.dump_schema_information
282
+ f.print "\n"
283
+ end
284
+ end
285
+ db_namespace['structure:dump'].reenable
286
+ end
287
+
288
+ desc "Recreate the databases from the structure.sql file"
289
+ task :load => [:environment, :load_config] do
290
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['DB_STRUCTURE'])
291
+ end
292
+
293
+ task :load_if_sql => ['db:create', :environment] do
294
+ db_namespace["structure:load"].invoke if ActiveRecord::Base.schema_format == :sql
295
+ end
296
+ end
297
+
298
+ namespace :test do
299
+
300
+ task :deprecated do
301
+ Rake.application.top_level_tasks.grep(/^db:test:/).each do |task|
302
+ $stderr.puts "WARNING: #{task} is deprecated. The Rails test helper now maintains " \
303
+ "your test schema automatically, see the release notes for details."
304
+ end
305
+ end
306
+
307
+ # desc "Recreate the test database from the current schema"
308
+ task :load => %w(db:test:purge) do
309
+ case ActiveRecord::Base.schema_format
310
+ when :ruby
311
+ db_namespace["test:load_schema"].invoke
312
+ when :sql
313
+ db_namespace["test:load_structure"].invoke
314
+ end
315
+ end
316
+
317
+ # desc "Recreate the test database from an existent schema.rb file"
318
+ task :load_schema => %w(db:test:purge) do
319
+ begin
320
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
321
+ ActiveRecord::Schema.verbose = false
322
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :ruby, ENV['SCHEMA']
323
+ ensure
324
+ if should_reconnect
325
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
326
+ end
327
+ end
328
+ end
329
+
330
+ # desc "Recreate the test database from an existent structure.sql file"
331
+ task :load_structure => %w(db:test:purge) do
332
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :sql, ENV['SCHEMA']
333
+ end
334
+
335
+ # desc "Recreate the test database from a fresh schema"
336
+ task :clone => %w(db:test:deprecated environment) do
337
+ case ActiveRecord::Base.schema_format
338
+ when :ruby
339
+ db_namespace["test:clone_schema"].invoke
340
+ when :sql
341
+ db_namespace["test:clone_structure"].invoke
342
+ end
343
+ end
344
+
345
+ # desc "Recreate the test database from a fresh schema.rb file"
346
+ task :clone_schema => %w(db:test:deprecated db:schema:dump db:test:load_schema)
347
+
348
+ # desc "Recreate the test database from a fresh structure.sql file"
349
+ task :clone_structure => %w(db:test:deprecated db:structure:dump db:test:load_structure)
350
+
351
+ # desc "Empty the test database"
352
+ task :purge => %w(environment load_config) do
353
+ ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations['test']
354
+ end
355
+
356
+ # desc 'Check for pending migrations and load the test schema'
357
+ task :prepare => %w(environment load_config) do
358
+ unless ActiveRecord::Base.configurations.blank?
359
+ db_namespace['test:load'].invoke
360
+ end
361
+ end
362
+ end
363
+ end
364
+
365
+ namespace :railties do
366
+ namespace :install do
367
+ # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
368
+ task :migrations => :'db:load_config' do
369
+ to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
370
+ railties = {}
371
+ Rails.application.migration_railties.each do |railtie|
372
+ next unless to_load == :all || to_load.include?(railtie.railtie_name)
373
+
374
+ if railtie.respond_to?(:paths) && (path = railtie.paths['db/migrate'].first)
375
+ railties[railtie.railtie_name] = path
376
+ end
377
+ end
378
+
379
+ on_skip = Proc.new do |name, migration|
380
+ puts "NOTE: Migration #{migration.basename} from #{name} has been skipped. Migration with the same name already exists."
381
+ end
382
+
383
+ on_copy = Proc.new do |name, migration|
384
+ puts "Copied migration #{migration.basename} from #{name}"
385
+ end
386
+
387
+ ActiveRecord::Migration.copy(ActiveRecord::Migrator.migrations_paths.first, railties,
388
+ :on_skip => on_skip, :on_copy => on_copy)
389
+ end
390
+ end
391
+ end