activerecord 4.2.0 → 5.2.8.1

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 (274) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +640 -928
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -11
  5. data/examples/performance.rb +32 -31
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +264 -247
  8. data/lib/active_record/association_relation.rb +24 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +87 -41
  11. data/lib/active_record/associations/association_scope.rb +106 -132
  12. data/lib/active_record/associations/belongs_to_association.rb +55 -36
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +29 -38
  15. data/lib/active_record/associations/builder/belongs_to.rb +77 -30
  16. data/lib/active_record/associations/builder/collection_association.rb +14 -23
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -39
  18. data/lib/active_record/associations/builder/has_many.rb +6 -4
  19. data/lib/active_record/associations/builder/has_one.rb +13 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +15 -11
  21. data/lib/active_record/associations/collection_association.rb +145 -266
  22. data/lib/active_record/associations/collection_proxy.rb +242 -138
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +35 -75
  25. data/lib/active_record/associations/has_many_through_association.rb +51 -69
  26. data/lib/active_record/associations/has_one_association.rb +39 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +40 -81
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +134 -154
  32. data/lib/active_record/associations/preloader/association.rb +85 -116
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +83 -93
  35. data/lib/active_record/associations/singular_association.rb +27 -40
  36. data/lib/active_record/associations/through_association.rb +48 -23
  37. data/lib/active_record/associations.rb +1732 -1596
  38. data/lib/active_record/attribute_assignment.rb +58 -182
  39. data/lib/active_record/attribute_decorators.rb +39 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -5
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -125
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -71
  43. data/lib/active_record/attribute_methods/query.rb +4 -2
  44. data/lib/active_record/attribute_methods/read.rb +45 -63
  45. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +62 -36
  47. data/lib/active_record/attribute_methods/write.rb +31 -46
  48. data/lib/active_record/attribute_methods.rb +170 -117
  49. data/lib/active_record/attributes.rb +201 -74
  50. data/lib/active_record/autosave_association.rb +118 -45
  51. data/lib/active_record/base.rb +60 -48
  52. data/lib/active_record/callbacks.rb +97 -57
  53. data/lib/active_record/coders/json.rb +3 -1
  54. data/lib/active_record/coders/yaml_column.rb +37 -13
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -284
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +254 -87
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +72 -22
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -217
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +617 -212
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +139 -75
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +332 -191
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +567 -563
  69. data/lib/active_record/connection_adapters/column.rb +50 -41
  70. data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +42 -195
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -115
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +65 -51
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +466 -280
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +439 -330
  117. data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -324
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +40 -27
  128. data/lib/active_record/core.rb +205 -202
  129. data/lib/active_record/counter_cache.rb +80 -37
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +87 -105
  132. data/lib/active_record/enum.rb +136 -90
  133. data/lib/active_record/errors.rb +180 -52
  134. data/lib/active_record/explain.rb +23 -11
  135. data/lib/active_record/explain_registry.rb +4 -2
  136. data/lib/active_record/explain_subscriber.rb +11 -6
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +193 -135
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +148 -112
  141. data/lib/active_record/integration.rb +70 -28
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +92 -98
  146. data/lib/active_record/locking/pessimistic.rb +15 -3
  147. data/lib/active_record/log_subscriber.rb +95 -33
  148. data/lib/active_record/migration/command_recorder.rb +133 -90
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +8 -6
  151. data/lib/active_record/migration.rb +594 -267
  152. data/lib/active_record/model_schema.rb +292 -111
  153. data/lib/active_record/nested_attributes.rb +266 -214
  154. data/lib/active_record/no_touching.rb +8 -2
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +350 -119
  157. data/lib/active_record/query_cache.rb +13 -24
  158. data/lib/active_record/querying.rb +19 -17
  159. data/lib/active_record/railtie.rb +117 -35
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +9 -3
  162. data/lib/active_record/railties/databases.rake +160 -174
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +447 -288
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +204 -55
  167. data/lib/active_record/relation/calculations.rb +259 -244
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +290 -253
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +91 -68
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -23
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  179. data/lib/active_record/relation/predicate_builder.rb +118 -92
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +446 -389
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +18 -16
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +287 -339
  187. data/lib/active_record/result.rb +54 -36
  188. data/lib/active_record/runtime_registry.rb +6 -4
  189. data/lib/active_record/sanitization.rb +155 -124
  190. data/lib/active_record/schema.rb +30 -24
  191. data/lib/active_record/schema_dumper.rb +91 -87
  192. data/lib/active_record/schema_migration.rb +19 -19
  193. data/lib/active_record/scoping/default.rb +102 -84
  194. data/lib/active_record/scoping/named.rb +81 -32
  195. data/lib/active_record/scoping.rb +45 -26
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +5 -5
  198. data/lib/active_record/statement_cache.rb +45 -35
  199. data/lib/active_record/store.rb +42 -36
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +136 -95
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +59 -89
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -31
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
  206. data/lib/active_record/timestamp.rb +70 -38
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +208 -123
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +4 -41
  212. data/lib/active_record/type/date_time.rb +4 -38
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +30 -15
  218. data/lib/active_record/type/text.rb +2 -2
  219. data/lib/active_record/type/time.rb +11 -16
  220. data/lib/active_record/type/type_map.rb +15 -17
  221. data/lib/active_record/type/unsigned_integer.rb +9 -7
  222. data/lib/active_record/type.rb +79 -23
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +13 -4
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +14 -13
  230. data/lib/active_record/validations/uniqueness.rb +41 -32
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +36 -21
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
  237. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -6
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -7
  239. data/lib/rails/generators/active_record/migration.rb +18 -1
  240. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
  242. data/lib/rails/generators/active_record.rb +7 -5
  243. metadata +77 -53
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  251. data/lib/active_record/attribute.rb +0 -149
  252. data/lib/active_record/attribute_set/builder.rb +0 -86
  253. data/lib/active_record/attribute_set.rb +0 -77
  254. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  255. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  256. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  257. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  258. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  259. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  260. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  261. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  262. data/lib/active_record/type/big_integer.rb +0 -13
  263. data/lib/active_record/type/binary.rb +0 -50
  264. data/lib/active_record/type/boolean.rb +0 -30
  265. data/lib/active_record/type/decimal.rb +0 -40
  266. data/lib/active_record/type/decorator.rb +0 -14
  267. data/lib/active_record/type/float.rb +0 -19
  268. data/lib/active_record/type/integer.rb +0 -55
  269. data/lib/active_record/type/mutable.rb +0 -16
  270. data/lib/active_record/type/numeric.rb +0 -36
  271. data/lib/active_record/type/string.rb +0 -36
  272. data/lib/active_record/type/time_value.rb +0 -38
  273. data/lib/active_record/type/value.rb +0 -101
  274. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,5 +1,6 @@
1
- require 'stringio'
2
- require 'active_support/core_ext/big_decimal'
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
3
4
 
4
5
  module ActiveRecord
5
6
  # = Active Record Schema Dumper
@@ -12,14 +13,13 @@ module ActiveRecord
12
13
  ##
13
14
  # :singleton-method:
14
15
  # A list of tables which should not be dumped to the schema.
15
- # Acceptable values are strings as well as regexp.
16
- # This setting is only used if ActiveRecord::Base.schema_format == :ruby
17
- cattr_accessor :ignore_tables
18
- @@ignore_tables = []
16
+ # Acceptable values are strings as well as regexp if ActiveRecord::Base.schema_format == :ruby.
17
+ # Only strings are accepted if ActiveRecord::Base.schema_format == :sql.
18
+ cattr_accessor :ignore_tables, default: []
19
19
 
20
20
  class << self
21
- def dump(connection=ActiveRecord::Base.connection, stream=STDOUT, config = ActiveRecord::Base)
22
- new(connection, generate_options(config)).dump(stream)
21
+ def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
22
+ connection.create_schema_dumper(generate_options(config)).dump(stream)
23
23
  stream
24
24
  end
25
25
 
@@ -44,18 +44,22 @@ module ActiveRecord
44
44
 
45
45
  def initialize(connection, options = {})
46
46
  @connection = connection
47
- @types = @connection.native_database_types
48
- @version = Migrator::current_version rescue nil
47
+ @version = connection.migration_context.current_version rescue nil
49
48
  @options = options
50
49
  end
51
50
 
52
- def header(stream)
53
- define_params = @version ? "version: #{@version}" : ""
51
+ # turns 20170404131909 into "2017_04_04_131909"
52
+ def formatted_version
53
+ stringified = @version.to_s
54
+ return stringified unless stringified.length == 14
55
+ stringified.insert(4, "_").insert(7, "_").insert(10, "_")
56
+ end
54
57
 
55
- if stream.respond_to?(:external_encoding) && stream.external_encoding
56
- stream.puts "# encoding: #{stream.external_encoding.name}"
57
- end
58
+ def define_params
59
+ @version ? "version: #{formatted_version}" : ""
60
+ end
58
61
 
62
+ def header(stream)
59
63
  stream.puts <<HEADER
60
64
  # This file is auto-generated from the current state of the database. Instead
61
65
  # of editing this file, please use the migrations feature of Active Record to
@@ -78,16 +82,8 @@ HEADER
78
82
  stream.puts "end"
79
83
  end
80
84
 
85
+ # extensions are only supported by PostgreSQL
81
86
  def extensions(stream)
82
- return unless @connection.supports_extensions?
83
- extensions = @connection.extensions
84
- if extensions.any?
85
- stream.puts " # These are extensions that must be enabled in order to support this database"
86
- extensions.each do |extension|
87
- stream.puts " enable_extension #{extension.inspect}"
88
- end
89
- stream.puts
90
- end
91
87
  end
92
88
 
93
89
  def tables(stream)
@@ -114,62 +110,43 @@ HEADER
114
110
  pk = @connection.primary_key(table)
115
111
 
116
112
  tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
117
- pkcol = columns.detect { |c| c.name == pk }
118
- if pkcol
119
- if pk != 'id'
120
- tbl.print %Q(, primary_key: "#{pk}")
121
- elsif pkcol.sql_type == 'bigint'
122
- tbl.print ", id: :bigserial"
123
- elsif pkcol.sql_type == 'uuid'
124
- tbl.print ", id: :uuid"
125
- tbl.print %Q(, default: "#{pkcol.default_function}") if pkcol.default_function
113
+
114
+ case pk
115
+ when String
116
+ tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
117
+ pkcol = columns.detect { |c| c.name == pk }
118
+ pkcolspec = column_spec_for_primary_key(pkcol)
119
+ if pkcolspec.present?
120
+ tbl.print ", #{format_colspec(pkcolspec)}"
126
121
  end
122
+ when Array
123
+ tbl.print ", primary_key: #{pk.inspect}"
127
124
  else
128
125
  tbl.print ", id: false"
129
126
  end
130
- tbl.print ", force: :cascade"
131
- tbl.puts " do |t|"
127
+
128
+ table_options = @connection.table_options(table)
129
+ if table_options.present?
130
+ tbl.print ", #{format_options(table_options)}"
131
+ end
132
+
133
+ tbl.puts ", force: :cascade do |t|"
132
134
 
133
135
  # then dump all non-primary key columns
134
- column_specs = columns.map do |column|
136
+ columns.each do |column|
135
137
  raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
136
138
  next if column.name == pk
137
- @connection.column_spec(column, @types)
138
- end.compact
139
-
140
- # find all migration keys used in this table
141
- keys = @connection.migration_keys
142
-
143
- # figure out the lengths for each column based on above keys
144
- lengths = keys.map { |key|
145
- column_specs.map { |spec|
146
- spec[key] ? spec[key].length + 2 : 0
147
- }.max
148
- }
149
-
150
- # the string we're going to sprintf our values against, with standardized column widths
151
- format_string = lengths.map{ |len| "%-#{len}s" }
152
-
153
- # find the max length for the 'type' column, which is special
154
- type_length = column_specs.map{ |column| column[:type].length }.max
155
-
156
- # add column type definition to our format string
157
- format_string.unshift " t.%-#{type_length}s "
158
-
159
- format_string *= ''
160
-
161
- column_specs.each do |colspec|
162
- values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
163
- values.unshift colspec[:type]
164
- tbl.print((format_string % values).gsub(/,\s*$/, ''))
139
+ type, colspec = column_spec(column)
140
+ tbl.print " t.#{type} #{column.name.inspect}"
141
+ tbl.print ", #{format_colspec(colspec)}" if colspec.present?
165
142
  tbl.puts
166
143
  end
167
144
 
145
+ indexes_in_create(table, tbl)
146
+
168
147
  tbl.puts " end"
169
148
  tbl.puts
170
149
 
171
- indexes(table, tbl)
172
-
173
150
  tbl.rewind
174
151
  stream.print tbl.read
175
152
  rescue => e
@@ -177,30 +154,14 @@ HEADER
177
154
  stream.puts "# #{e.message}"
178
155
  stream.puts
179
156
  end
180
-
181
- stream
182
157
  end
183
158
 
159
+ # Keep it for indexing materialized views
184
160
  def indexes(table, stream)
185
161
  if (indexes = @connection.indexes(table)).any?
186
162
  add_index_statements = indexes.map do |index|
187
- statement_parts = [
188
- "add_index #{remove_prefix_and_suffix(index.table).inspect}",
189
- index.columns.inspect,
190
- "name: #{index.name.inspect}",
191
- ]
192
- statement_parts << 'unique: true' if index.unique
193
-
194
- index_lengths = (index.lengths || []).compact
195
- statement_parts << "length: #{Hash[index.columns.zip(index.lengths)].inspect}" if index_lengths.any?
196
-
197
- index_orders = index.orders || {}
198
- statement_parts << "order: #{index.orders.inspect}" if index_orders.any?
199
- statement_parts << "where: #{index.where.inspect}" if index.where
200
- statement_parts << "using: #{index.using.inspect}" if index.using
201
- statement_parts << "type: #{index.type.inspect}" if index.type
202
-
203
- " #{statement_parts.join(', ')}"
163
+ table_name = remove_prefix_and_suffix(index.table).inspect
164
+ " add_index #{([table_name] + index_parts(index)).join(', ')}"
204
165
  end
205
166
 
206
167
  stream.puts add_index_statements.sort.join("\n")
@@ -208,6 +169,31 @@ HEADER
208
169
  end
209
170
  end
210
171
 
172
+ def indexes_in_create(table, stream)
173
+ if (indexes = @connection.indexes(table)).any?
174
+ index_statements = indexes.map do |index|
175
+ " t.index #{index_parts(index).join(', ')}"
176
+ end
177
+ stream.puts index_statements.sort.join("\n")
178
+ end
179
+ end
180
+
181
+ def index_parts(index)
182
+ index_parts = [
183
+ index.columns.inspect,
184
+ "name: #{index.name.inspect}",
185
+ ]
186
+ index_parts << "unique: true" if index.unique
187
+ index_parts << "length: #{format_index_parts(index.lengths)}" if index.lengths.present?
188
+ index_parts << "order: #{format_index_parts(index.orders)}" if index.orders.present?
189
+ index_parts << "opclass: #{format_index_parts(index.opclasses)}" if index.opclasses.present?
190
+ index_parts << "where: #{index.where.inspect}" if index.where
191
+ index_parts << "using: #{index.using.inspect}" if !@connection.default_index_type?(index)
192
+ index_parts << "type: #{index.type.inspect}" if index.type
193
+ index_parts << "comment: #{index.comment.inspect}" if index.comment
194
+ index_parts
195
+ end
196
+
211
197
  def foreign_keys(table, stream)
212
198
  if (foreign_keys = @connection.foreign_keys(table)).any?
213
199
  add_foreign_key_statements = foreign_keys.map do |foreign_key|
@@ -238,12 +224,30 @@ HEADER
238
224
  end
239
225
  end
240
226
 
227
+ def format_colspec(colspec)
228
+ colspec.map { |key, value| "#{key}: #{value}" }.join(", ")
229
+ end
230
+
231
+ def format_options(options)
232
+ options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
233
+ end
234
+
235
+ def format_index_parts(options)
236
+ if options.is_a?(Hash)
237
+ "{ #{format_options(options)} }"
238
+ else
239
+ options.inspect
240
+ end
241
+ end
242
+
241
243
  def remove_prefix_and_suffix(table)
242
- table.gsub(/^(#{@options[:table_name_prefix]})(.+)(#{@options[:table_name_suffix]})$/, "\\2")
244
+ prefix = Regexp.escape(@options[:table_name_prefix].to_s)
245
+ suffix = Regexp.escape(@options[:table_name_suffix].to_s)
246
+ table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
243
247
  end
244
248
 
245
249
  def ignored?(table_name)
246
- ['schema_migrations', ignore_tables].flatten.any? do |ignored|
250
+ [ActiveRecord::Base.schema_migrations_table_name, ActiveRecord::Base.internal_metadata_table_name, ignore_tables].flatten.any? do |ignored|
247
251
  ignored === remove_prefix_and_suffix(table_name)
248
252
  end
249
253
  end
@@ -1,43 +1,39 @@
1
- require 'active_record/scoping/default'
2
- require 'active_record/scoping/named'
3
- require 'active_record/base'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/scoping/default"
4
+ require "active_record/scoping/named"
4
5
 
5
6
  module ActiveRecord
6
- class SchemaMigration < ActiveRecord::Base
7
+ # This class is used to create a table that keeps track of which migrations
8
+ # have been applied to a given database. When a migration is run, its schema
9
+ # number is inserted in to the `SchemaMigration.table_name` so it doesn't need
10
+ # to be executed the next time.
11
+ class SchemaMigration < ActiveRecord::Base # :nodoc:
7
12
  class << self
8
13
  def primary_key
9
- nil
14
+ "version"
10
15
  end
11
16
 
12
17
  def table_name
13
18
  "#{table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{table_name_suffix}"
14
19
  end
15
20
 
16
- def index_name
17
- "#{table_name_prefix}unique_#{ActiveRecord::Base.schema_migrations_table_name}#{table_name_suffix}"
18
- end
19
-
20
21
  def table_exists?
21
22
  connection.table_exists?(table_name)
22
23
  end
23
24
 
24
- def create_table(limit=nil)
25
+ def create_table
25
26
  unless table_exists?
26
- version_options = {null: false}
27
- version_options[:limit] = limit if limit
27
+ version_options = connection.internal_string_options_for_primary_key
28
28
 
29
29
  connection.create_table(table_name, id: false) do |t|
30
- t.column :version, :string, version_options
30
+ t.string :version, version_options
31
31
  end
32
- connection.add_index table_name, :version, unique: true, name: index_name
33
32
  end
34
33
  end
35
34
 
36
35
  def drop_table
37
- if table_exists?
38
- connection.remove_index table_name, name: index_name
39
- connection.drop_table(table_name)
40
- end
36
+ connection.drop_table table_name, if_exists: true
41
37
  end
42
38
 
43
39
  def normalize_migration_number(number)
@@ -45,7 +41,11 @@ module ActiveRecord
45
41
  end
46
42
 
47
43
  def normalized_versions
48
- pluck(:version).map { |v| normalize_migration_number v }
44
+ all_versions.map { |v| normalize_migration_number v }
45
+ end
46
+
47
+ def all_versions
48
+ order(:version).pluck(:version)
49
49
  end
50
50
  end
51
51
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Scoping
3
5
  module Default
@@ -5,9 +7,8 @@ module ActiveRecord
5
7
 
6
8
  included do
7
9
  # Stores the default scope for the class.
8
- class_attribute :default_scopes, instance_writer: false, instance_predicate: false
9
-
10
- self.default_scopes = []
10
+ class_attribute :default_scopes, instance_writer: false, instance_predicate: false, default: []
11
+ class_attribute :default_scope_override, instance_writer: false, instance_predicate: false, default: nil
11
12
  end
12
13
 
13
14
  module ClassMethods
@@ -15,7 +16,7 @@ module ActiveRecord
15
16
  #
16
17
  # class Post < ActiveRecord::Base
17
18
  # def self.default_scope
18
- # where published: true
19
+ # where(published: true)
19
20
  # end
20
21
  # end
21
22
  #
@@ -33,101 +34,118 @@ module ActiveRecord
33
34
  block_given? ? relation.scoping { yield } : relation
34
35
  end
35
36
 
37
+ # Are there attributes associated with this scope?
38
+ def scope_attributes? # :nodoc:
39
+ super || default_scopes.any? || respond_to?(:default_scope)
40
+ end
41
+
36
42
  def before_remove_const #:nodoc:
37
43
  self.current_scope = nil
38
44
  end
39
45
 
40
- protected
46
+ private
41
47
 
42
- # Use this macro in your model to set a default scope for all operations on
43
- # the model.
44
- #
45
- # class Article < ActiveRecord::Base
46
- # default_scope { where(published: true) }
47
- # end
48
- #
49
- # Article.all # => SELECT * FROM articles WHERE published = true
50
- #
51
- # The +default_scope+ is also applied while creating/building a record.
52
- # It is not applied while updating a record.
53
- #
54
- # Article.new.published # => true
55
- # Article.create.published # => true
56
- #
57
- # (You can also pass any object which responds to +call+ to the
58
- # +default_scope+ macro, and it will be called when building the
59
- # default scope.)
60
- #
61
- # If you use multiple +default_scope+ declarations in your model then
62
- # they will be merged together:
63
- #
64
- # class Article < ActiveRecord::Base
65
- # default_scope { where(published: true) }
66
- # default_scope { where(rating: 'G') }
67
- # end
68
- #
69
- # Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
70
- #
71
- # This is also the case with inheritance and module includes where the
72
- # parent or module defines a +default_scope+ and the child or including
73
- # class defines a second one.
74
- #
75
- # If you need to do more complex things with a default scope, you can
76
- # alternatively define it as a class method:
77
- #
78
- # class Article < ActiveRecord::Base
79
- # def self.default_scope
80
- # # Should return a scope, you can call 'super' here etc.
81
- # end
82
- # end
83
- def default_scope(scope = nil)
84
- scope = Proc.new if block_given?
85
-
86
- if scope.is_a?(Relation) || !scope.respond_to?(:call)
87
- raise ArgumentError,
88
- "Support for calling #default_scope without a block is removed. For example instead " \
89
- "of `default_scope where(color: 'red')`, please use " \
90
- "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
91
- "self.default_scope.)"
48
+ # Use this macro in your model to set a default scope for all operations on
49
+ # the model.
50
+ #
51
+ # class Article < ActiveRecord::Base
52
+ # default_scope { where(published: true) }
53
+ # end
54
+ #
55
+ # Article.all # => SELECT * FROM articles WHERE published = true
56
+ #
57
+ # The #default_scope is also applied while creating/building a record.
58
+ # It is not applied while updating a record.
59
+ #
60
+ # Article.new.published # => true
61
+ # Article.create.published # => true
62
+ #
63
+ # (You can also pass any object which responds to +call+ to the
64
+ # +default_scope+ macro, and it will be called when building the
65
+ # default scope.)
66
+ #
67
+ # If you use multiple #default_scope declarations in your model then
68
+ # they will be merged together:
69
+ #
70
+ # class Article < ActiveRecord::Base
71
+ # default_scope { where(published: true) }
72
+ # default_scope { where(rating: 'G') }
73
+ # end
74
+ #
75
+ # Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
76
+ #
77
+ # This is also the case with inheritance and module includes where the
78
+ # parent or module defines a #default_scope and the child or including
79
+ # class defines a second one.
80
+ #
81
+ # If you need to do more complex things with a default scope, you can
82
+ # alternatively define it as a class method:
83
+ #
84
+ # class Article < ActiveRecord::Base
85
+ # def self.default_scope
86
+ # # Should return a scope, you can call 'super' here etc.
87
+ # end
88
+ # end
89
+ def default_scope(scope = nil, &block) # :doc:
90
+ scope = block if block_given?
91
+
92
+ if scope.is_a?(Relation) || !scope.respond_to?(:call)
93
+ raise ArgumentError,
94
+ "Support for calling #default_scope without a block is removed. For example instead " \
95
+ "of `default_scope where(color: 'red')`, please use " \
96
+ "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
97
+ "self.default_scope.)"
98
+ end
99
+
100
+ self.default_scopes += [scope]
92
101
  end
93
102
 
94
- self.default_scopes += [scope]
95
- end
103
+ def build_default_scope(base_rel = nil)
104
+ return if abstract_class?
105
+
106
+ if default_scope_override.nil?
107
+ self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
108
+ end
96
109
 
97
- def build_default_scope(base_rel = relation) # :nodoc:
98
- if !Base.is_a?(method(:default_scope).owner)
99
- # The user has defined their own default scope method, so call that
100
- evaluate_default_scope { default_scope }
101
- elsif default_scopes.any?
102
- evaluate_default_scope do
103
- default_scopes.inject(base_rel) do |default_scope, scope|
104
- default_scope.merge(base_rel.scoping { scope.call })
110
+ if default_scope_override
111
+ # The user has defined their own default scope method, so call that
112
+ evaluate_default_scope do
113
+ if scope = default_scope
114
+ (base_rel ||= relation).merge!(scope)
115
+ end
116
+ end
117
+ elsif default_scopes.any?
118
+ base_rel ||= relation
119
+ evaluate_default_scope do
120
+ default_scopes.inject(base_rel) do |default_scope, scope|
121
+ scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
122
+ default_scope.merge!(base_rel.instance_exec(&scope))
123
+ end
105
124
  end
106
125
  end
107
126
  end
108
- end
109
127
 
110
- def ignore_default_scope? # :nodoc:
111
- ScopeRegistry.value_for(:ignore_default_scope, self)
112
- end
128
+ def ignore_default_scope?
129
+ ScopeRegistry.value_for(:ignore_default_scope, base_class)
130
+ end
113
131
 
114
- def ignore_default_scope=(ignore) # :nodoc:
115
- ScopeRegistry.set_value_for(:ignore_default_scope, self, ignore)
116
- end
132
+ def ignore_default_scope=(ignore)
133
+ ScopeRegistry.set_value_for(:ignore_default_scope, base_class, ignore)
134
+ end
135
+
136
+ # The ignore_default_scope flag is used to prevent an infinite recursion
137
+ # situation where a default scope references a scope which has a default
138
+ # scope which references a scope...
139
+ def evaluate_default_scope
140
+ return if ignore_default_scope?
117
141
 
118
- # The ignore_default_scope flag is used to prevent an infinite recursion
119
- # situation where a default scope references a scope which has a default
120
- # scope which references a scope...
121
- def evaluate_default_scope # :nodoc:
122
- return if ignore_default_scope?
123
-
124
- begin
125
- self.ignore_default_scope = true
126
- yield
127
- ensure
128
- self.ignore_default_scope = false
142
+ begin
143
+ self.ignore_default_scope = true
144
+ yield
145
+ ensure
146
+ self.ignore_default_scope = false
147
+ end
129
148
  end
130
- end
131
149
  end
132
150
  end
133
151
  end