activerecord 3.2.19 → 5.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 (264) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1715 -604
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +40 -45
  5. data/examples/performance.rb +33 -22
  6. data/examples/simple.rb +3 -4
  7. data/lib/active_record/aggregations.rb +76 -51
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +54 -40
  10. data/lib/active_record/associations/association.rb +76 -56
  11. data/lib/active_record/associations/association_scope.rb +125 -93
  12. data/lib/active_record/associations/belongs_to_association.rb +57 -28
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  14. data/lib/active_record/associations/builder/association.rb +120 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +115 -62
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -53
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +117 -43
  18. data/lib/active_record/associations/builder/has_many.rb +9 -65
  19. data/lib/active_record/associations/builder/has_one.rb +18 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +18 -19
  21. data/lib/active_record/associations/collection_association.rb +268 -186
  22. data/lib/active_record/associations/collection_proxy.rb +1003 -63
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +81 -41
  25. data/lib/active_record/associations/has_many_through_association.rb +76 -55
  26. data/lib/active_record/associations/has_one_association.rb +51 -21
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +83 -108
  29. data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
  31. data/lib/active_record/associations/join_dependency.rb +239 -155
  32. data/lib/active_record/associations/preloader/association.rb +97 -62
  33. data/lib/active_record/associations/preloader/collection_association.rb +2 -8
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +75 -33
  38. data/lib/active_record/associations/preloader.rb +111 -79
  39. data/lib/active_record/associations/singular_association.rb +35 -13
  40. data/lib/active_record/associations/through_association.rb +41 -19
  41. data/lib/active_record/associations.rb +727 -501
  42. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  43. data/lib/active_record/attribute.rb +213 -0
  44. data/lib/active_record/attribute_assignment.rb +32 -162
  45. data/lib/active_record/attribute_decorators.rb +67 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  47. data/lib/active_record/attribute_methods/dirty.rb +101 -61
  48. data/lib/active_record/attribute_methods/primary_key.rb +50 -36
  49. data/lib/active_record/attribute_methods/query.rb +7 -6
  50. data/lib/active_record/attribute_methods/read.rb +56 -117
  51. data/lib/active_record/attribute_methods/serialization.rb +43 -96
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +93 -42
  53. data/lib/active_record/attribute_methods/write.rb +34 -45
  54. data/lib/active_record/attribute_methods.rb +333 -144
  55. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  56. data/lib/active_record/attribute_set/builder.rb +108 -0
  57. data/lib/active_record/attribute_set.rb +108 -0
  58. data/lib/active_record/attributes.rb +265 -0
  59. data/lib/active_record/autosave_association.rb +285 -223
  60. data/lib/active_record/base.rb +95 -490
  61. data/lib/active_record/callbacks.rb +95 -61
  62. data/lib/active_record/coders/json.rb +13 -0
  63. data/lib/active_record/coders/yaml_column.rb +28 -19
  64. data/lib/active_record/collection_cache_key.rb +40 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +724 -277
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -192
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -26
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +140 -57
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +147 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +419 -276
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +105 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +963 -276
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +232 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +397 -106
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +643 -342
  78. data/lib/active_record/connection_adapters/column.rb +30 -259
  79. data/lib/active_record/connection_adapters/connection_specification.rb +263 -0
  80. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  81. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  82. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  83. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  84. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  89. data/lib/active_record/connection_adapters/mysql2_adapter.rb +47 -196
  90. data/lib/active_record/connection_adapters/postgresql/column.rb +15 -0
  91. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +170 -0
  92. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +70 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +48 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +21 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +10 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +39 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +93 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid.rb +31 -0
  115. data/lib/active_record/connection_adapters/postgresql/quoting.rb +116 -0
  116. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +49 -0
  117. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +180 -0
  118. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  119. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +682 -0
  120. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  121. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  122. data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -1039
  123. data/lib/active_record/connection_adapters/schema_cache.rb +74 -36
  124. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  125. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +538 -24
  129. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  130. data/lib/active_record/connection_handling.rb +155 -0
  131. data/lib/active_record/core.rb +561 -0
  132. data/lib/active_record/counter_cache.rb +146 -105
  133. data/lib/active_record/dynamic_matchers.rb +101 -64
  134. data/lib/active_record/enum.rb +234 -0
  135. data/lib/active_record/errors.rb +153 -56
  136. data/lib/active_record/explain.rb +15 -63
  137. data/lib/active_record/explain_registry.rb +30 -0
  138. data/lib/active_record/explain_subscriber.rb +10 -6
  139. data/lib/active_record/fixture_set/file.rb +77 -0
  140. data/lib/active_record/fixtures.rb +355 -232
  141. data/lib/active_record/gem_version.rb +15 -0
  142. data/lib/active_record/inheritance.rb +144 -79
  143. data/lib/active_record/integration.rb +66 -13
  144. data/lib/active_record/internal_metadata.rb +56 -0
  145. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  146. data/lib/active_record/locale/en.yml +9 -1
  147. data/lib/active_record/locking/optimistic.rb +77 -56
  148. data/lib/active_record/locking/pessimistic.rb +6 -6
  149. data/lib/active_record/log_subscriber.rb +53 -28
  150. data/lib/active_record/migration/command_recorder.rb +166 -33
  151. data/lib/active_record/migration/compatibility.rb +126 -0
  152. data/lib/active_record/migration/join_table.rb +15 -0
  153. data/lib/active_record/migration.rb +792 -264
  154. data/lib/active_record/model_schema.rb +192 -130
  155. data/lib/active_record/nested_attributes.rb +238 -145
  156. data/lib/active_record/no_touching.rb +52 -0
  157. data/lib/active_record/null_relation.rb +89 -0
  158. data/lib/active_record/persistence.rb +357 -157
  159. data/lib/active_record/query_cache.rb +22 -43
  160. data/lib/active_record/querying.rb +34 -23
  161. data/lib/active_record/railtie.rb +88 -48
  162. data/lib/active_record/railties/console_sandbox.rb +3 -4
  163. data/lib/active_record/railties/controller_runtime.rb +5 -4
  164. data/lib/active_record/railties/databases.rake +170 -422
  165. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  166. data/lib/active_record/readonly_attributes.rb +2 -5
  167. data/lib/active_record/reflection.rb +715 -189
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  169. data/lib/active_record/relation/batches.rb +203 -50
  170. data/lib/active_record/relation/calculations.rb +203 -194
  171. data/lib/active_record/relation/delegation.rb +103 -25
  172. data/lib/active_record/relation/finder_methods.rb +457 -261
  173. data/lib/active_record/relation/from_clause.rb +32 -0
  174. data/lib/active_record/relation/merger.rb +167 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +43 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  179. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  180. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  181. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  182. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  183. data/lib/active_record/relation/predicate_builder.rb +153 -48
  184. data/lib/active_record/relation/query_attribute.rb +19 -0
  185. data/lib/active_record/relation/query_methods.rb +1019 -194
  186. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  187. data/lib/active_record/relation/spawn_methods.rb +46 -150
  188. data/lib/active_record/relation/where_clause.rb +174 -0
  189. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  190. data/lib/active_record/relation.rb +450 -245
  191. data/lib/active_record/result.rb +104 -12
  192. data/lib/active_record/runtime_registry.rb +22 -0
  193. data/lib/active_record/sanitization.rb +120 -94
  194. data/lib/active_record/schema.rb +28 -18
  195. data/lib/active_record/schema_dumper.rb +141 -74
  196. data/lib/active_record/schema_migration.rb +50 -0
  197. data/lib/active_record/scoping/default.rb +64 -57
  198. data/lib/active_record/scoping/named.rb +93 -108
  199. data/lib/active_record/scoping.rb +73 -121
  200. data/lib/active_record/secure_token.rb +38 -0
  201. data/lib/active_record/serialization.rb +7 -5
  202. data/lib/active_record/statement_cache.rb +113 -0
  203. data/lib/active_record/store.rb +173 -15
  204. data/lib/active_record/suppressor.rb +58 -0
  205. data/lib/active_record/table_metadata.rb +68 -0
  206. data/lib/active_record/tasks/database_tasks.rb +313 -0
  207. data/lib/active_record/tasks/mysql_database_tasks.rb +151 -0
  208. data/lib/active_record/tasks/postgresql_database_tasks.rb +110 -0
  209. data/lib/active_record/tasks/sqlite_database_tasks.rb +59 -0
  210. data/lib/active_record/timestamp.rb +42 -24
  211. data/lib/active_record/touch_later.rb +58 -0
  212. data/lib/active_record/transactions.rb +233 -105
  213. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  214. data/lib/active_record/type/date.rb +7 -0
  215. data/lib/active_record/type/date_time.rb +7 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  217. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  218. data/lib/active_record/type/internal/timezone.rb +15 -0
  219. data/lib/active_record/type/serialized.rb +63 -0
  220. data/lib/active_record/type/time.rb +20 -0
  221. data/lib/active_record/type/type_map.rb +64 -0
  222. data/lib/active_record/type.rb +72 -0
  223. data/lib/active_record/type_caster/connection.rb +29 -0
  224. data/lib/active_record/type_caster/map.rb +19 -0
  225. data/lib/active_record/type_caster.rb +7 -0
  226. data/lib/active_record/validations/absence.rb +23 -0
  227. data/lib/active_record/validations/associated.rb +33 -18
  228. data/lib/active_record/validations/length.rb +24 -0
  229. data/lib/active_record/validations/presence.rb +66 -0
  230. data/lib/active_record/validations/uniqueness.rb +128 -68
  231. data/lib/active_record/validations.rb +48 -40
  232. data/lib/active_record/version.rb +5 -7
  233. data/lib/active_record.rb +71 -47
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +56 -8
  235. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +24 -0
  236. data/lib/rails/generators/active_record/migration/templates/migration.rb +28 -16
  237. data/lib/rails/generators/active_record/migration.rb +18 -8
  238. data/lib/rails/generators/active_record/model/model_generator.rb +38 -16
  239. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  240. data/lib/rails/generators/active_record/model/templates/model.rb +7 -6
  241. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  242. data/lib/rails/generators/active_record.rb +3 -11
  243. metadata +188 -134
  244. data/examples/associations.png +0 -0
  245. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  246. data/lib/active_record/associations/join_helper.rb +0 -55
  247. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  248. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  249. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  250. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  251. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  252. data/lib/active_record/dynamic_finder_match.rb +0 -68
  253. data/lib/active_record/dynamic_scope_match.rb +0 -23
  254. data/lib/active_record/fixtures/file.rb +0 -65
  255. data/lib/active_record/identity_map.rb +0 -162
  256. data/lib/active_record/observer.rb +0 -121
  257. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  258. data/lib/active_record/session_store.rb +0 -360
  259. data/lib/active_record/test_case.rb +0 -73
  260. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  261. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  262. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  263. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  264. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,5 +1,4 @@
1
1
  require 'stringio'
2
- require 'active_support/core_ext/big_decimal'
3
2
 
4
3
  module ActiveRecord
5
4
  # = Active Record Schema Dumper
@@ -17,13 +16,24 @@ module ActiveRecord
17
16
  cattr_accessor :ignore_tables
18
17
  @@ignore_tables = []
19
18
 
20
- def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT)
21
- new(connection).dump(stream)
22
- stream
19
+ class << self
20
+ def dump(connection=ActiveRecord::Base.connection, stream=STDOUT, config = ActiveRecord::Base)
21
+ new(connection, generate_options(config)).dump(stream)
22
+ stream
23
+ end
24
+
25
+ private
26
+ def generate_options(config)
27
+ {
28
+ table_name_prefix: config.table_name_prefix,
29
+ table_name_suffix: config.table_name_suffix
30
+ }
31
+ end
23
32
  end
24
33
 
25
34
  def dump(stream)
26
35
  header(stream)
36
+ extensions(stream)
27
37
  tables(stream)
28
38
  trailer(stream)
29
39
  stream
@@ -31,18 +41,14 @@ module ActiveRecord
31
41
 
32
42
  private
33
43
 
34
- def initialize(connection)
44
+ def initialize(connection, options = {})
35
45
  @connection = connection
36
- @types = @connection.native_database_types
37
46
  @version = Migrator::current_version rescue nil
47
+ @options = options
38
48
  end
39
49
 
40
50
  def header(stream)
41
- define_params = @version ? ":version => #{@version}" : ""
42
-
43
- if stream.respond_to?(:external_encoding) && stream.external_encoding
44
- stream.puts "# encoding: #{stream.external_encoding.name}"
45
- end
51
+ define_params = @version ? "version: #{@version}" : ""
46
52
 
47
53
  stream.puts <<HEADER
48
54
  # This file is auto-generated from the current state of the database. Instead
@@ -55,7 +61,7 @@ module ActiveRecord
55
61
  # from scratch. The latter is a flawed and unsustainable approach (the more migrations
56
62
  # you'll amass, the slower it'll run and the greater likelihood for issues).
57
63
  #
58
- # It's strongly recommended to check this file into your version control system.
64
+ # It's strongly recommended that you check this file into your version control system.
59
65
 
60
66
  ActiveRecord::Schema.define(#{define_params}) do
61
67
 
@@ -66,17 +72,30 @@ HEADER
66
72
  stream.puts "end"
67
73
  end
68
74
 
75
+ def extensions(stream)
76
+ return unless @connection.supports_extensions?
77
+ extensions = @connection.extensions
78
+ if extensions.any?
79
+ stream.puts " # These are extensions that must be enabled in order to support this database"
80
+ extensions.each do |extension|
81
+ stream.puts " enable_extension #{extension.inspect}"
82
+ end
83
+ stream.puts
84
+ end
85
+ end
86
+
69
87
  def tables(stream)
70
- @connection.tables.sort.each do |tbl|
71
- next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
72
- case ignored
73
- when String; remove_prefix_and_suffix(tbl) == ignored
74
- when Regexp; remove_prefix_and_suffix(tbl) =~ ignored
75
- else
76
- raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.'
77
- end
88
+ sorted_tables = @connection.data_sources.sort - @connection.views
89
+
90
+ sorted_tables.each do |table_name|
91
+ table(table_name, stream) unless ignored?(table_name)
92
+ end
93
+
94
+ # dump foreign keys at the end to make sure all dependent tables exist.
95
+ if @connection.supports_foreign_keys?
96
+ sorted_tables.each do |tbl|
97
+ foreign_keys(tbl, stream) unless ignored?(tbl)
78
98
  end
79
- table(tbl, stream)
80
99
  end
81
100
  end
82
101
 
@@ -86,51 +105,57 @@ HEADER
86
105
  tbl = StringIO.new
87
106
 
88
107
  # first dump primary key column
89
- if @connection.respond_to?(:pk_and_sequence_for)
90
- pk, _ = @connection.pk_and_sequence_for(table)
91
- elsif @connection.respond_to?(:primary_key)
108
+ if @connection.respond_to?(:primary_keys)
109
+ pk = @connection.primary_keys(table)
110
+ pk = pk.first unless pk.size > 1
111
+ else
92
112
  pk = @connection.primary_key(table)
93
113
  end
94
114
 
95
115
  tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
96
- if columns.detect { |c| c.name == pk }
97
- if pk != 'id'
98
- tbl.print %Q(, :primary_key => "#{pk}")
116
+
117
+ case pk
118
+ when String
119
+ tbl.print ", primary_key: #{pk.inspect}" unless pk == 'id'
120
+ pkcol = columns.detect { |c| c.name == pk }
121
+ pkcolspec = @connection.column_spec_for_primary_key(pkcol)
122
+ if pkcolspec.present?
123
+ pkcolspec.each do |key, value|
124
+ tbl.print ", #{key}: #{value}"
125
+ end
99
126
  end
127
+ when Array
128
+ tbl.print ", primary_key: #{pk.inspect}"
100
129
  else
101
- tbl.print ", :id => false"
130
+ tbl.print ", id: false"
131
+ end
132
+ tbl.print ", force: :cascade"
133
+
134
+ table_options = @connection.table_options(table)
135
+ tbl.print ", options: #{table_options.inspect}" unless table_options.blank?
136
+
137
+ if comment = @connection.table_comment(table).presence
138
+ tbl.print ", comment: #{comment.inspect}"
102
139
  end
103
- tbl.print ", :force => true"
140
+
104
141
  tbl.puts " do |t|"
105
142
 
106
143
  # then dump all non-primary key columns
107
144
  column_specs = columns.map do |column|
108
- raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
145
+ raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
109
146
  next if column.name == pk
110
- spec = {}
111
- spec[:name] = column.name.inspect
112
-
113
- # AR has an optimization which handles zero-scale decimals as integers. This
114
- # code ensures that the dumper still dumps the column as a decimal.
115
- spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
116
- 'decimal'
117
- else
118
- column.type.to_s
119
- end
120
- spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal'
121
- spec[:precision] = column.precision.inspect if column.precision
122
- spec[:scale] = column.scale.inspect if column.scale
123
- spec[:null] = 'false' unless column.null
124
- spec[:default] = default_string(column.default) if column.has_default?
125
- (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
126
- spec
147
+ @connection.column_spec(column)
127
148
  end.compact
128
149
 
129
150
  # find all migration keys used in this table
130
- keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map{ |k| k.keys }.flatten
151
+ keys = @connection.migration_keys
131
152
 
132
153
  # figure out the lengths for each column based on above keys
133
- lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
154
+ lengths = keys.map { |key|
155
+ column_specs.map { |spec|
156
+ spec[key] ? spec[key].length + 2 : 0
157
+ }.max
158
+ }
134
159
 
135
160
  # the string we're going to sprintf our values against, with standardized column widths
136
161
  format_string = lengths.map{ |len| "%-#{len}s" }
@@ -150,11 +175,11 @@ HEADER
150
175
  tbl.puts
151
176
  end
152
177
 
178
+ indexes_in_create(table, tbl)
179
+
153
180
  tbl.puts " end"
154
181
  tbl.puts
155
182
 
156
- indexes(table, tbl)
157
-
158
183
  tbl.rewind
159
184
  stream.print tbl.read
160
185
  rescue => e
@@ -166,43 +191,85 @@ HEADER
166
191
  stream
167
192
  end
168
193
 
169
- def default_string(value)
170
- case value
171
- when BigDecimal
172
- value.to_s
173
- when Date, DateTime, Time
174
- "'" + value.to_s(:db) + "'"
175
- else
176
- value.inspect
194
+ # Keep it for indexing materialized views
195
+ def indexes(table, stream)
196
+ if (indexes = @connection.indexes(table)).any?
197
+ add_index_statements = indexes.map do |index|
198
+ table_name = remove_prefix_and_suffix(index.table).inspect
199
+ " add_index #{([table_name]+index_parts(index)).join(', ')}"
200
+ end
201
+
202
+ stream.puts add_index_statements.sort.join("\n")
203
+ stream.puts
177
204
  end
178
205
  end
179
206
 
180
- def indexes(table, stream)
207
+ def indexes_in_create(table, stream)
181
208
  if (indexes = @connection.indexes(table)).any?
182
- add_index_statements = indexes.map do |index|
183
- statement_parts = [
184
- ('add_index ' + remove_prefix_and_suffix(index.table).inspect),
185
- index.columns.inspect,
186
- (':name => ' + index.name.inspect),
209
+ index_statements = indexes.map do |index|
210
+ " t.index #{index_parts(index).join(', ')}"
211
+ end
212
+ stream.puts index_statements.sort.join("\n")
213
+ end
214
+ end
215
+
216
+ def index_parts(index)
217
+ index_parts = [
218
+ index.columns.inspect,
219
+ "name: #{index.name.inspect}",
220
+ ]
221
+ index_parts << 'unique: true' if index.unique
222
+
223
+ index_lengths = (index.lengths || []).compact
224
+ index_parts << "length: #{Hash[index.columns.zip(index.lengths)].inspect}" if index_lengths.any?
225
+
226
+ index_orders = index.orders || {}
227
+ index_parts << "order: #{index.orders.inspect}" if index_orders.any?
228
+ index_parts << "where: #{index.where.inspect}" if index.where
229
+ index_parts << "using: #{index.using.inspect}" if index.using
230
+ index_parts << "type: #{index.type.inspect}" if index.type
231
+ index_parts << "comment: #{index.comment.inspect}" if index.comment
232
+ index_parts
233
+ end
234
+
235
+ def foreign_keys(table, stream)
236
+ if (foreign_keys = @connection.foreign_keys(table)).any?
237
+ add_foreign_key_statements = foreign_keys.map do |foreign_key|
238
+ parts = [
239
+ "add_foreign_key #{remove_prefix_and_suffix(foreign_key.from_table).inspect}",
240
+ remove_prefix_and_suffix(foreign_key.to_table).inspect,
187
241
  ]
188
- statement_parts << ':unique => true' if index.unique
189
242
 
190
- index_lengths = (index.lengths || []).compact
191
- statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty?
243
+ if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table)
244
+ parts << "column: #{foreign_key.column.inspect}"
245
+ end
246
+
247
+ if foreign_key.custom_primary_key?
248
+ parts << "primary_key: #{foreign_key.primary_key.inspect}"
249
+ end
250
+
251
+ if foreign_key.name !~ /^fk_rails_[0-9a-f]{10}$/
252
+ parts << "name: #{foreign_key.name.inspect}"
253
+ end
192
254
 
193
- index_orders = (index.orders || {})
194
- statement_parts << (':order => ' + index.orders.inspect) unless index_orders.empty?
255
+ parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
256
+ parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
195
257
 
196
- ' ' + statement_parts.join(', ')
258
+ " #{parts.join(', ')}"
197
259
  end
198
260
 
199
- stream.puts add_index_statements.sort.join("\n")
200
- stream.puts
261
+ stream.puts add_foreign_key_statements.sort.join("\n")
201
262
  end
202
263
  end
203
264
 
204
265
  def remove_prefix_and_suffix(table)
205
- table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
266
+ table.gsub(/^(#{@options[:table_name_prefix]})(.+)(#{@options[:table_name_suffix]})$/, "\\2")
267
+ end
268
+
269
+ def ignored?(table_name)
270
+ [ActiveRecord::Base.schema_migrations_table_name, ActiveRecord::Base.internal_metadata_table_name, ignore_tables].flatten.any? do |ignored|
271
+ ignored === remove_prefix_and_suffix(table_name)
272
+ end
206
273
  end
207
274
  end
208
275
  end
@@ -0,0 +1,50 @@
1
+ require 'active_record/scoping/default'
2
+ require 'active_record/scoping/named'
3
+
4
+ module ActiveRecord
5
+ # This class is used to create a table that keeps track of which migrations
6
+ # have been applied to a given database. When a migration is run, its schema
7
+ # number is inserted in to the `SchemaMigration.table_name` so it doesn't need
8
+ # to be executed the next time.
9
+ class SchemaMigration < ActiveRecord::Base # :nodoc:
10
+ class << self
11
+ def primary_key
12
+ "version"
13
+ end
14
+
15
+ def table_name
16
+ "#{table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{table_name_suffix}"
17
+ end
18
+
19
+ def table_exists?
20
+ ActiveSupport::Deprecation.silence { connection.table_exists?(table_name) }
21
+ end
22
+
23
+ def create_table
24
+ unless table_exists?
25
+ version_options = connection.internal_string_options_for_primary_key
26
+
27
+ connection.create_table(table_name, id: false) do |t|
28
+ t.string :version, version_options
29
+ end
30
+ end
31
+ end
32
+
33
+ def drop_table
34
+ connection.drop_table table_name, if_exists: true
35
+ end
36
+
37
+ def normalize_migration_number(number)
38
+ "%.3d" % number.to_i
39
+ end
40
+
41
+ def normalized_versions
42
+ pluck(:version).map { |v| normalize_migration_number v }
43
+ end
44
+ end
45
+
46
+ def version
47
+ super.to_i
48
+ end
49
+ end
50
+ end
@@ -1,46 +1,45 @@
1
- require 'active_support/concern'
2
-
3
1
  module ActiveRecord
4
2
  module Scoping
5
3
  module Default
6
4
  extend ActiveSupport::Concern
7
5
 
8
6
  included do
9
- # Stores the default scope for the class
10
- class_attribute :default_scopes, :instance_writer => false
7
+ # Stores the default scope for the class.
8
+ class_attribute :default_scopes, instance_writer: false, instance_predicate: false
9
+ class_attribute :default_scope_override, instance_writer: false, instance_predicate: false
10
+
11
11
  self.default_scopes = []
12
+ self.default_scope_override = nil
12
13
  end
13
14
 
14
15
  module ClassMethods
15
- # Returns a scope for the model without the default_scope.
16
+ # Returns a scope for the model without the previously set scopes.
16
17
  #
17
18
  # class Post < ActiveRecord::Base
18
19
  # def self.default_scope
19
- # where :published => true
20
+ # where(published: true)
20
21
  # end
21
22
  # end
22
23
  #
23
- # Post.all # Fires "SELECT * FROM posts WHERE published = true"
24
- # Post.unscoped.all # Fires "SELECT * FROM posts"
24
+ # Post.all # Fires "SELECT * FROM posts WHERE published = true"
25
+ # Post.unscoped.all # Fires "SELECT * FROM posts"
26
+ # Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts"
25
27
  #
26
28
  # This method also accepts a block. All queries inside the block will
27
- # not use the default_scope:
29
+ # not use the previously set scopes.
28
30
  #
29
31
  # Post.unscoped {
30
32
  # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
31
33
  # }
32
- #
33
- # It is recommended to use the block form of unscoped because chaining
34
- # unscoped with <tt>scope</tt> does not work. Assuming that
35
- # <tt>published</tt> is a <tt>scope</tt>, the following two statements
36
- # are equal: the default_scope is applied on both.
37
- #
38
- # Post.unscoped.published
39
- # Post.published
40
- def unscoped #:nodoc:
34
+ def unscoped
41
35
  block_given? ? relation.scoping { yield } : relation
42
36
  end
43
37
 
38
+ # Are there attributes associated with this scope?
39
+ def scope_attributes? # :nodoc:
40
+ super || default_scopes.any? || respond_to?(:default_scope)
41
+ end
42
+
44
43
  def before_remove_const #:nodoc:
45
44
  self.current_scope = nil
46
45
  end
@@ -51,81 +50,90 @@ module ActiveRecord
51
50
  # the model.
52
51
  #
53
52
  # class Article < ActiveRecord::Base
54
- # default_scope where(:published => true)
53
+ # default_scope { where(published: true) }
55
54
  # end
56
55
  #
57
56
  # Article.all # => SELECT * FROM articles WHERE published = true
58
57
  #
59
- # The <tt>default_scope</tt> is also applied while creating/building a record. It is not
60
- # applied while updating a record.
58
+ # The #default_scope is also applied while creating/building a record.
59
+ # It is not applied while updating a record.
61
60
  #
62
61
  # Article.new.published # => true
63
62
  # Article.create.published # => true
64
63
  #
65
- # You can also use <tt>default_scope</tt> with a block, in order to have it lazily evaluated:
66
- #
67
- # class Article < ActiveRecord::Base
68
- # default_scope { where(:published_at => Time.now - 1.week) }
69
- # end
64
+ # (You can also pass any object which responds to +call+ to the
65
+ # +default_scope+ macro, and it will be called when building the
66
+ # default scope.)
70
67
  #
71
- # (You can also pass any object which responds to <tt>call</tt> to the <tt>default_scope</tt>
72
- # macro, and it will be called when building the default scope.)
73
- #
74
- # If you use multiple <tt>default_scope</tt> declarations in your model then they will
75
- # be merged together:
68
+ # If you use multiple #default_scope declarations in your model then
69
+ # they will be merged together:
76
70
  #
77
71
  # class Article < ActiveRecord::Base
78
- # default_scope where(:published => true)
79
- # default_scope where(:rating => 'G')
72
+ # default_scope { where(published: true) }
73
+ # default_scope { where(rating: 'G') }
80
74
  # end
81
75
  #
82
76
  # Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
83
77
  #
84
- # This is also the case with inheritance and module includes where the parent or module
85
- # defines a <tt>default_scope</tt> and the child or including class defines a second one.
78
+ # This is also the case with inheritance and module includes where the
79
+ # parent or module defines a #default_scope and the child or including
80
+ # class defines a second one.
86
81
  #
87
- # If you need to do more complex things with a default scope, you can alternatively
88
- # define it as a class method:
82
+ # If you need to do more complex things with a default scope, you can
83
+ # alternatively define it as a class method:
89
84
  #
90
85
  # class Article < ActiveRecord::Base
91
86
  # def self.default_scope
92
87
  # # Should return a scope, you can call 'super' here etc.
93
88
  # end
94
89
  # end
95
- def default_scope(scope = {})
90
+ def default_scope(scope = nil)
96
91
  scope = Proc.new if block_given?
97
- self.default_scopes = default_scopes + [scope]
92
+
93
+ if scope.is_a?(Relation) || !scope.respond_to?(:call)
94
+ raise ArgumentError,
95
+ "Support for calling #default_scope without a block is removed. For example instead " \
96
+ "of `default_scope where(color: 'red')`, please use " \
97
+ "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
98
+ "self.default_scope.)"
99
+ end
100
+
101
+ self.default_scopes += [scope]
98
102
  end
99
103
 
100
- def build_default_scope #:nodoc:
101
- if method(:default_scope).owner != ActiveRecord::Scoping::Default::ClassMethods
104
+ def build_default_scope(base_rel = nil) # :nodoc:
105
+ return if abstract_class?
106
+
107
+ if self.default_scope_override.nil?
108
+ self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
109
+ end
110
+
111
+ if self.default_scope_override
112
+ # The user has defined their own default scope method, so call that
102
113
  evaluate_default_scope { default_scope }
103
114
  elsif default_scopes.any?
115
+ base_rel ||= relation
104
116
  evaluate_default_scope do
105
- default_scopes.inject(relation) do |default_scope, scope|
106
- if scope.is_a?(Hash)
107
- default_scope.apply_finder_options(scope)
108
- elsif !scope.is_a?(Relation) && scope.respond_to?(:call)
109
- default_scope.merge(scope.call)
110
- else
111
- default_scope.merge(scope)
112
- end
117
+ default_scopes.inject(base_rel) do |default_scope, scope|
118
+ scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
119
+ default_scope.merge(base_rel.instance_exec(&scope))
113
120
  end
114
121
  end
115
122
  end
116
123
  end
117
124
 
118
- def ignore_default_scope? #:nodoc:
119
- Thread.current["#{self}_ignore_default_scope"]
125
+ def ignore_default_scope? # :nodoc:
126
+ ScopeRegistry.value_for(:ignore_default_scope, base_class)
120
127
  end
121
128
 
122
- def ignore_default_scope=(ignore) #:nodoc:
123
- Thread.current["#{self}_ignore_default_scope"] = ignore
129
+ def ignore_default_scope=(ignore) # :nodoc:
130
+ ScopeRegistry.set_value_for(:ignore_default_scope, base_class, ignore)
124
131
  end
125
132
 
126
- # The ignore_default_scope flag is used to prevent an infinite recursion situation where
127
- # a default scope references a scope which has a default scope which references a scope...
128
- def evaluate_default_scope
133
+ # The ignore_default_scope flag is used to prevent an infinite recursion
134
+ # situation where a default scope references a scope which has a default
135
+ # scope which references a scope...
136
+ def evaluate_default_scope # :nodoc:
129
137
  return if ignore_default_scope?
130
138
 
131
139
  begin
@@ -135,7 +143,6 @@ module ActiveRecord
135
143
  self.ignore_default_scope = false
136
144
  end
137
145
  end
138
-
139
146
  end
140
147
  end
141
148
  end