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,251 @@
1
+ require 'stringio'
2
+ require 'active_support/core_ext/big_decimal'
3
+
4
+ module ActiveRecord
5
+ # = Active Record Schema Dumper
6
+ #
7
+ # This class is used to dump the database schema for some connection to some
8
+ # output format (i.e., ActiveRecord::Schema).
9
+ class SchemaDumper #:nodoc:
10
+ private_class_method :new
11
+
12
+ ##
13
+ # :singleton-method:
14
+ # 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 = []
19
+
20
+ class << self
21
+ def dump(connection=ActiveRecord::Base.connection, stream=STDOUT, config = ActiveRecord::Base)
22
+ new(connection, generate_options(config)).dump(stream)
23
+ stream
24
+ end
25
+
26
+ private
27
+ def generate_options(config)
28
+ {
29
+ table_name_prefix: config.table_name_prefix,
30
+ table_name_suffix: config.table_name_suffix
31
+ }
32
+ end
33
+ end
34
+
35
+ def dump(stream)
36
+ header(stream)
37
+ extensions(stream)
38
+ tables(stream)
39
+ trailer(stream)
40
+ stream
41
+ end
42
+
43
+ private
44
+
45
+ def initialize(connection, options = {})
46
+ @connection = connection
47
+ @types = @connection.native_database_types
48
+ @version = Migrator::current_version rescue nil
49
+ @options = options
50
+ end
51
+
52
+ def header(stream)
53
+ define_params = @version ? "version: #{@version}" : ""
54
+
55
+ if stream.respond_to?(:external_encoding) && stream.external_encoding
56
+ stream.puts "# encoding: #{stream.external_encoding.name}"
57
+ end
58
+
59
+ stream.puts <<HEADER
60
+ # This file is auto-generated from the current state of the database. Instead
61
+ # of editing this file, please use the migrations feature of Active Record to
62
+ # incrementally modify your database, and then regenerate this schema definition.
63
+ #
64
+ # Note that this schema.rb definition is the authoritative source for your
65
+ # database schema. If you need to create the application database on another
66
+ # system, you should be using db:schema:load, not running all the migrations
67
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
68
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
69
+ #
70
+ # It's strongly recommended that you check this file into your version control system.
71
+
72
+ ActiveRecord::Schema.define(#{define_params}) do
73
+
74
+ HEADER
75
+ end
76
+
77
+ def trailer(stream)
78
+ stream.puts "end"
79
+ end
80
+
81
+ 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
+ end
92
+
93
+ def tables(stream)
94
+ sorted_tables = @connection.tables.sort
95
+
96
+ sorted_tables.each do |table_name|
97
+ table(table_name, stream) unless ignored?(table_name)
98
+ end
99
+
100
+ # dump foreign keys at the end to make sure all dependent tables exist.
101
+ if @connection.supports_foreign_keys?
102
+ sorted_tables.each do |tbl|
103
+ foreign_keys(tbl, stream) unless ignored?(tbl)
104
+ end
105
+ end
106
+ end
107
+
108
+ def table(table, stream)
109
+ columns = @connection.columns(table)
110
+ begin
111
+ tbl = StringIO.new
112
+
113
+ # first dump primary key column
114
+ pk = @connection.primary_key(table)
115
+
116
+ 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
126
+ end
127
+ else
128
+ tbl.print ", id: false"
129
+ end
130
+ tbl.print ", force: :cascade"
131
+ tbl.puts " do |t|"
132
+
133
+ # then dump all non-primary key columns
134
+ column_specs = columns.map do |column|
135
+ raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
136
+ 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*$/, ''))
165
+ tbl.puts
166
+ end
167
+
168
+ tbl.puts " end"
169
+ tbl.puts
170
+
171
+ indexes(table, tbl)
172
+
173
+ tbl.rewind
174
+ stream.print tbl.read
175
+ rescue => e
176
+ stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
177
+ stream.puts "# #{e.message}"
178
+ stream.puts
179
+ end
180
+
181
+ stream
182
+ end
183
+
184
+ def indexes(table, stream)
185
+ if (indexes = @connection.indexes(table)).any?
186
+ 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(', ')}"
204
+ end
205
+
206
+ stream.puts add_index_statements.sort.join("\n")
207
+ stream.puts
208
+ end
209
+ end
210
+
211
+ def foreign_keys(table, stream)
212
+ if (foreign_keys = @connection.foreign_keys(table)).any?
213
+ add_foreign_key_statements = foreign_keys.map do |foreign_key|
214
+ parts = [
215
+ "add_foreign_key #{remove_prefix_and_suffix(foreign_key.from_table).inspect}",
216
+ remove_prefix_and_suffix(foreign_key.to_table).inspect,
217
+ ]
218
+
219
+ if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table)
220
+ parts << "column: #{foreign_key.column.inspect}"
221
+ end
222
+
223
+ if foreign_key.custom_primary_key?
224
+ parts << "primary_key: #{foreign_key.primary_key.inspect}"
225
+ end
226
+
227
+ if foreign_key.name !~ /^fk_rails_[0-9a-f]{10}$/
228
+ parts << "name: #{foreign_key.name.inspect}"
229
+ end
230
+
231
+ parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
232
+ parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
233
+
234
+ " #{parts.join(', ')}"
235
+ end
236
+
237
+ stream.puts add_foreign_key_statements.sort.join("\n")
238
+ end
239
+ end
240
+
241
+ def remove_prefix_and_suffix(table)
242
+ table.gsub(/^(#{@options[:table_name_prefix]})(.+)(#{@options[:table_name_suffix]})$/, "\\2")
243
+ end
244
+
245
+ def ignored?(table_name)
246
+ ['schema_migrations', ignore_tables].flatten.any? do |ignored|
247
+ ignored === remove_prefix_and_suffix(table_name)
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,56 @@
1
+ require 'active_record/scoping/default'
2
+ require 'active_record/scoping/named'
3
+ require 'active_record/base'
4
+
5
+ module ActiveRecord
6
+ class SchemaMigration < ActiveRecord::Base
7
+ class << self
8
+ def primary_key
9
+ nil
10
+ end
11
+
12
+ def table_name
13
+ "#{table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{table_name_suffix}"
14
+ end
15
+
16
+ def index_name
17
+ "#{table_name_prefix}unique_#{ActiveRecord::Base.schema_migrations_table_name}#{table_name_suffix}"
18
+ end
19
+
20
+ def table_exists?
21
+ connection.table_exists?(table_name)
22
+ end
23
+
24
+ def create_table(limit=nil)
25
+ unless table_exists?
26
+ version_options = {null: false}
27
+ version_options[:limit] = limit if limit
28
+
29
+ connection.create_table(table_name, id: false) do |t|
30
+ t.column :version, :string, version_options
31
+ end
32
+ connection.add_index table_name, :version, unique: true, name: index_name
33
+ end
34
+ end
35
+
36
+ def drop_table
37
+ if table_exists?
38
+ connection.remove_index table_name, name: index_name
39
+ connection.drop_table(table_name)
40
+ end
41
+ end
42
+
43
+ def normalize_migration_number(number)
44
+ "%.3d" % number.to_i
45
+ end
46
+
47
+ def normalized_versions
48
+ pluck(:version).map { |v| normalize_migration_number v }
49
+ end
50
+ end
51
+
52
+ def version
53
+ super.to_i
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,87 @@
1
+ require 'active_support/per_thread_registry'
2
+
3
+ module ActiveRecord
4
+ module Scoping
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include Default
9
+ include Named
10
+ end
11
+
12
+ module ClassMethods
13
+ def current_scope #:nodoc:
14
+ ScopeRegistry.value_for(:current_scope, base_class.to_s)
15
+ end
16
+
17
+ def current_scope=(scope) #:nodoc:
18
+ ScopeRegistry.set_value_for(:current_scope, base_class.to_s, scope)
19
+ end
20
+ end
21
+
22
+ def populate_with_current_scope_attributes
23
+ return unless self.class.scope_attributes?
24
+
25
+ self.class.scope_attributes.each do |att,value|
26
+ send("#{att}=", value) if respond_to?("#{att}=")
27
+ end
28
+ end
29
+
30
+ def initialize_internals_callback
31
+ super
32
+ populate_with_current_scope_attributes
33
+ end
34
+
35
+ # This class stores the +:current_scope+ and +:ignore_default_scope+ values
36
+ # for different classes. The registry is stored as a thread local, which is
37
+ # accessed through +ScopeRegistry.current+.
38
+ #
39
+ # This class allows you to store and get the scope values on different
40
+ # classes and different types of scopes. For example, if you are attempting
41
+ # to get the current_scope for the +Board+ model, then you would use the
42
+ # following code:
43
+ #
44
+ # registry = ActiveRecord::Scoping::ScopeRegistry
45
+ # registry.set_value_for(:current_scope, "Board", some_new_scope)
46
+ #
47
+ # Now when you run:
48
+ #
49
+ # registry.value_for(:current_scope, "Board")
50
+ #
51
+ # You will obtain whatever was defined in +some_new_scope+. The +value_for+
52
+ # and +set_value_for+ methods are delegated to the current +ScopeRegistry+
53
+ # object, so the above example code can also be called as:
54
+ #
55
+ # ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
56
+ # "Board", some_new_scope)
57
+ class ScopeRegistry # :nodoc:
58
+ extend ActiveSupport::PerThreadRegistry
59
+
60
+ VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope]
61
+
62
+ def initialize
63
+ @registry = Hash.new { |hash, key| hash[key] = {} }
64
+ end
65
+
66
+ # Obtains the value for a given +scope_name+ and +variable_name+.
67
+ def value_for(scope_type, variable_name)
68
+ raise_invalid_scope_type!(scope_type)
69
+ @registry[scope_type][variable_name]
70
+ end
71
+
72
+ # Sets the +value+ for a given +scope_type+ and +variable_name+.
73
+ def set_value_for(scope_type, variable_name, value)
74
+ raise_invalid_scope_type!(scope_type)
75
+ @registry[scope_type][variable_name] = value
76
+ end
77
+
78
+ private
79
+
80
+ def raise_invalid_scope_type!(scope_type)
81
+ if !VALID_SCOPE_TYPES.include?(scope_type)
82
+ raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,134 @@
1
+ module ActiveRecord
2
+ module Scoping
3
+ module Default
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ # Stores the default scope for the class.
8
+ class_attribute :default_scopes, instance_writer: false, instance_predicate: false
9
+
10
+ self.default_scopes = []
11
+ end
12
+
13
+ module ClassMethods
14
+ # Returns a scope for the model without the previously set scopes.
15
+ #
16
+ # class Post < ActiveRecord::Base
17
+ # def self.default_scope
18
+ # where published: true
19
+ # end
20
+ # end
21
+ #
22
+ # Post.all # Fires "SELECT * FROM posts WHERE published = true"
23
+ # Post.unscoped.all # Fires "SELECT * FROM posts"
24
+ # Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts"
25
+ #
26
+ # This method also accepts a block. All queries inside the block will
27
+ # not use the previously set scopes.
28
+ #
29
+ # Post.unscoped {
30
+ # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
31
+ # }
32
+ def unscoped
33
+ block_given? ? relation.scoping { yield } : relation
34
+ end
35
+
36
+ def before_remove_const #:nodoc:
37
+ self.current_scope = nil
38
+ end
39
+
40
+ protected
41
+
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.)"
92
+ end
93
+
94
+ self.default_scopes += [scope]
95
+ end
96
+
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 })
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ def ignore_default_scope? # :nodoc:
111
+ ScopeRegistry.value_for(:ignore_default_scope, self)
112
+ end
113
+
114
+ def ignore_default_scope=(ignore) # :nodoc:
115
+ ScopeRegistry.set_value_for(:ignore_default_scope, self, ignore)
116
+ end
117
+
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
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end