activerecord 4.1.16 → 4.2.0.beta1

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +634 -2185
  3. data/README.rdoc +15 -10
  4. data/lib/active_record.rb +2 -1
  5. data/lib/active_record/aggregations.rb +12 -8
  6. data/lib/active_record/associations.rb +58 -33
  7. data/lib/active_record/associations/association.rb +1 -1
  8. data/lib/active_record/associations/association_scope.rb +53 -21
  9. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  10. data/lib/active_record/associations/builder/association.rb +16 -5
  11. data/lib/active_record/associations/builder/belongs_to.rb +7 -29
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -11
  13. data/lib/active_record/associations/builder/has_one.rb +2 -2
  14. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  15. data/lib/active_record/associations/collection_association.rb +32 -44
  16. data/lib/active_record/associations/collection_proxy.rb +1 -10
  17. data/lib/active_record/associations/has_many_association.rb +60 -14
  18. data/lib/active_record/associations/has_many_through_association.rb +34 -23
  19. data/lib/active_record/associations/has_one_association.rb +0 -1
  20. data/lib/active_record/associations/join_dependency.rb +7 -9
  21. data/lib/active_record/associations/join_dependency/join_association.rb +18 -14
  22. data/lib/active_record/associations/preloader.rb +2 -2
  23. data/lib/active_record/associations/preloader/association.rb +9 -5
  24. data/lib/active_record/associations/preloader/through_association.rb +3 -3
  25. data/lib/active_record/associations/singular_association.rb +16 -1
  26. data/lib/active_record/associations/through_association.rb +6 -22
  27. data/lib/active_record/attribute.rb +131 -0
  28. data/lib/active_record/attribute_assignment.rb +19 -11
  29. data/lib/active_record/attribute_decorators.rb +66 -0
  30. data/lib/active_record/attribute_methods.rb +53 -90
  31. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -2
  32. data/lib/active_record/attribute_methods/dirty.rb +85 -42
  33. data/lib/active_record/attribute_methods/primary_key.rb +6 -8
  34. data/lib/active_record/attribute_methods/read.rb +14 -57
  35. data/lib/active_record/attribute_methods/serialization.rb +12 -146
  36. data/lib/active_record/attribute_methods/time_zone_conversion.rb +32 -40
  37. data/lib/active_record/attribute_methods/write.rb +8 -23
  38. data/lib/active_record/attribute_set.rb +77 -0
  39. data/lib/active_record/attribute_set/builder.rb +32 -0
  40. data/lib/active_record/attributes.rb +122 -0
  41. data/lib/active_record/autosave_association.rb +11 -21
  42. data/lib/active_record/base.rb +9 -19
  43. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +69 -45
  44. data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -42
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -60
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +37 -2
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +102 -21
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +9 -33
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +178 -55
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +120 -115
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +143 -57
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +156 -107
  53. data/lib/active_record/connection_adapters/column.rb +13 -244
  54. data/lib/active_record/connection_adapters/connection_specification.rb +6 -20
  55. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -15
  56. data/lib/active_record/connection_adapters/mysql_adapter.rb +55 -143
  57. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  58. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  59. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +39 -20
  60. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
  61. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +96 -0
  62. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  63. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  64. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
  65. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  66. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  67. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
  68. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  69. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +76 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +85 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  86. data/lib/active_record/connection_adapters/postgresql/quoting.rb +42 -122
  87. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  88. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +154 -0
  89. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +86 -34
  90. data/lib/active_record/connection_adapters/postgresql/utils.rb +66 -0
  91. data/lib/active_record/connection_adapters/postgresql_adapter.rb +188 -452
  92. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  93. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +54 -47
  94. data/lib/active_record/connection_handling.rb +1 -1
  95. data/lib/active_record/core.rb +119 -22
  96. data/lib/active_record/counter_cache.rb +60 -6
  97. data/lib/active_record/enum.rb +9 -10
  98. data/lib/active_record/errors.rb +27 -26
  99. data/lib/active_record/explain.rb +1 -1
  100. data/lib/active_record/fixtures.rb +52 -45
  101. data/lib/active_record/gem_version.rb +3 -3
  102. data/lib/active_record/inheritance.rb +33 -8
  103. data/lib/active_record/integration.rb +4 -4
  104. data/lib/active_record/locking/optimistic.rb +34 -16
  105. data/lib/active_record/migration.rb +22 -32
  106. data/lib/active_record/migration/command_recorder.rb +19 -2
  107. data/lib/active_record/migration/join_table.rb +1 -1
  108. data/lib/active_record/model_schema.rb +39 -48
  109. data/lib/active_record/nested_attributes.rb +8 -18
  110. data/lib/active_record/persistence.rb +39 -22
  111. data/lib/active_record/query_cache.rb +3 -3
  112. data/lib/active_record/querying.rb +1 -8
  113. data/lib/active_record/railtie.rb +17 -10
  114. data/lib/active_record/railties/databases.rake +47 -42
  115. data/lib/active_record/readonly_attributes.rb +0 -1
  116. data/lib/active_record/reflection.rb +225 -92
  117. data/lib/active_record/relation.rb +35 -11
  118. data/lib/active_record/relation/batches.rb +0 -2
  119. data/lib/active_record/relation/calculations.rb +28 -32
  120. data/lib/active_record/relation/delegation.rb +1 -1
  121. data/lib/active_record/relation/finder_methods.rb +42 -20
  122. data/lib/active_record/relation/merger.rb +0 -1
  123. data/lib/active_record/relation/predicate_builder.rb +1 -22
  124. data/lib/active_record/relation/predicate_builder/array_handler.rb +16 -11
  125. data/lib/active_record/relation/predicate_builder/relation_handler.rb +0 -4
  126. data/lib/active_record/relation/query_methods.rb +98 -62
  127. data/lib/active_record/relation/spawn_methods.rb +6 -7
  128. data/lib/active_record/result.rb +16 -9
  129. data/lib/active_record/sanitization.rb +8 -1
  130. data/lib/active_record/schema.rb +0 -1
  131. data/lib/active_record/schema_dumper.rb +51 -9
  132. data/lib/active_record/schema_migration.rb +4 -0
  133. data/lib/active_record/scoping/default.rb +5 -4
  134. data/lib/active_record/serializers/xml_serializer.rb +3 -7
  135. data/lib/active_record/statement_cache.rb +79 -5
  136. data/lib/active_record/store.rb +5 -5
  137. data/lib/active_record/tasks/database_tasks.rb +37 -5
  138. data/lib/active_record/tasks/mysql_database_tasks.rb +10 -16
  139. data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -2
  140. data/lib/active_record/timestamp.rb +9 -7
  141. data/lib/active_record/transactions.rb +35 -21
  142. data/lib/active_record/type.rb +20 -0
  143. data/lib/active_record/type/binary.rb +40 -0
  144. data/lib/active_record/type/boolean.rb +19 -0
  145. data/lib/active_record/type/date.rb +46 -0
  146. data/lib/active_record/type/date_time.rb +43 -0
  147. data/lib/active_record/type/decimal.rb +40 -0
  148. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  149. data/lib/active_record/type/float.rb +19 -0
  150. data/lib/active_record/type/hash_lookup_type_map.rb +19 -0
  151. data/lib/active_record/type/integer.rb +23 -0
  152. data/lib/active_record/type/mutable.rb +16 -0
  153. data/lib/active_record/type/numeric.rb +36 -0
  154. data/lib/active_record/type/serialized.rb +51 -0
  155. data/lib/active_record/type/string.rb +36 -0
  156. data/lib/active_record/type/text.rb +11 -0
  157. data/lib/active_record/type/time.rb +26 -0
  158. data/lib/active_record/type/time_value.rb +38 -0
  159. data/lib/active_record/type/type_map.rb +48 -0
  160. data/lib/active_record/type/value.rb +101 -0
  161. data/lib/active_record/validations.rb +21 -16
  162. data/lib/active_record/validations/uniqueness.rb +9 -23
  163. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  164. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
  165. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  166. metadata +71 -14
  167. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -92,7 +92,7 @@ module ActiveRecord
92
92
 
93
93
  table = Arel::Table.new(table_name, arel_engine).alias(default_table_name)
94
94
  PredicateBuilder.build_from_hash(self, attrs, table).map { |b|
95
- connection.visitor.accept b
95
+ connection.visitor.compile b
96
96
  }.join(' AND ')
97
97
  end
98
98
  alias_method :sanitize_sql_hash, :sanitize_sql_hash_for_conditions
@@ -107,6 +107,13 @@ module ActiveRecord
107
107
  end.join(', ')
108
108
  end
109
109
 
110
+ # Sanitizes a +string+ so that it is safe to use within an SQL
111
+ # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%"
112
+ def sanitize_sql_like(string, escape_character = "\\")
113
+ pattern = Regexp.union(escape_character, "%", "_")
114
+ string.gsub(pattern) { |x| [escape_character, x].join }
115
+ end
116
+
110
117
  # Accepts an array of conditions. The array has each value
111
118
  # sanitized and interpolated into the SQL statement.
112
119
  # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'"
@@ -1,4 +1,3 @@
1
-
2
1
  module ActiveRecord
3
2
  # = Active Record Schema
4
3
  #
@@ -91,16 +91,17 @@ HEADER
91
91
  end
92
92
 
93
93
  def tables(stream)
94
- @connection.tables.sort.each do |tbl|
95
- next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
96
- case ignored
97
- when String; remove_prefix_and_suffix(tbl) == ignored
98
- when Regexp; remove_prefix_and_suffix(tbl) =~ ignored
99
- else
100
- raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.'
101
- end
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)
102
104
  end
103
- table(tbl, stream)
104
105
  end
105
106
  end
106
107
 
@@ -213,8 +214,49 @@ HEADER
213
214
  end
214
215
  end
215
216
 
217
+ def foreign_keys(table, stream)
218
+ if (foreign_keys = @connection.foreign_keys(table)).any?
219
+ add_foreign_key_statements = foreign_keys.map do |foreign_key|
220
+ parts = [
221
+ 'add_foreign_key ' + remove_prefix_and_suffix(foreign_key.from_table).inspect,
222
+ remove_prefix_and_suffix(foreign_key.to_table).inspect,
223
+ ]
224
+
225
+ if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table)
226
+ parts << ('column: ' + foreign_key.column.inspect)
227
+ end
228
+
229
+ if foreign_key.custom_primary_key?
230
+ parts << ('primary_key: ' + foreign_key.primary_key.inspect)
231
+ end
232
+
233
+ if foreign_key.name !~ /^fk_rails_[0-9a-f]{10}$/
234
+ parts << ('name: ' + foreign_key.name.inspect)
235
+ end
236
+
237
+ parts << ('on_update: ' + foreign_key.on_update.inspect) if foreign_key.on_update
238
+ parts << ('on_delete: ' + foreign_key.on_delete.inspect) if foreign_key.on_delete
239
+
240
+ ' ' + parts.join(', ')
241
+ end
242
+
243
+ stream.puts add_foreign_key_statements.sort.join("\n")
244
+ end
245
+ end
246
+
216
247
  def remove_prefix_and_suffix(table)
217
248
  table.gsub(/^(#{@options[:table_name_prefix]})(.+)(#{@options[:table_name_suffix]})$/, "\\2")
218
249
  end
250
+
251
+ def ignored?(table_name)
252
+ ['schema_migrations', ignore_tables].flatten.any? do |ignored|
253
+ case ignored
254
+ when String; remove_prefix_and_suffix(table_name) == ignored
255
+ when Regexp; remove_prefix_and_suffix(table_name) =~ ignored
256
+ else
257
+ raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.'
258
+ end
259
+ end
260
+ end
219
261
  end
220
262
  end
@@ -43,6 +43,10 @@ module ActiveRecord
43
43
  def normalize_migration_number(number)
44
44
  "%.3d" % number.to_i
45
45
  end
46
+
47
+ def normalized_versions
48
+ pluck(:version).map { |v| normalize_migration_number v }
49
+ end
46
50
  end
47
51
 
48
52
  def version
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  end
12
12
 
13
13
  module ClassMethods
14
- # Returns a scope for the model without the +default_scope+.
14
+ # Returns a scope for the model without the previously set scopes.
15
15
  #
16
16
  # class Post < ActiveRecord::Base
17
17
  # def self.default_scope
@@ -19,11 +19,12 @@ module ActiveRecord
19
19
  # end
20
20
  # end
21
21
  #
22
- # Post.all # Fires "SELECT * FROM posts WHERE published = true"
23
- # Post.unscoped.all # Fires "SELECT * FROM posts"
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"
24
25
  #
25
26
  # This method also accepts a block. All queries inside the block will
26
- # not use the +default_scope+:
27
+ # not use the previously set scopes.
27
28
  #
28
29
  # Post.unscoped {
29
30
  # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
@@ -180,13 +180,9 @@ module ActiveRecord #:nodoc:
180
180
  class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
181
181
  def compute_type
182
182
  klass = @serializable.class
183
- type = if klass.serialized_attributes.key?(name)
184
- super
185
- elsif klass.columns_hash.key?(name)
186
- klass.columns_hash[name].type
187
- else
188
- NilClass
189
- end
183
+ column = klass.columns_hash[name] || Type::Value.new
184
+
185
+ type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name] || column.type
190
186
 
191
187
  { :text => :string,
192
188
  :time => :datetime }[type] || type
@@ -14,13 +14,87 @@ module ActiveRecord
14
14
  # The relation returned by the block is cached, and for each +execute+ call the cached relation gets duped.
15
15
  # Database is queried when +to_a+ is called on the relation.
16
16
  class StatementCache
17
- def initialize
18
- @relation = yield
19
- raise ArgumentError.new("Statement cannot be nil") if @relation.nil?
17
+ class Substitute; end
18
+
19
+ class Query
20
+ def initialize(sql)
21
+ @sql = sql
22
+ end
23
+
24
+ def sql_for(binds, connection)
25
+ @sql
26
+ end
27
+ end
28
+
29
+ class PartialQuery < Query
30
+ def initialize values
31
+ @values = values
32
+ @indexes = values.each_with_index.find_all { |thing,i|
33
+ Arel::Nodes::BindParam === thing
34
+ }.map(&:last)
35
+ end
36
+
37
+ def sql_for(binds, connection)
38
+ val = @values.dup
39
+ binds = binds.dup
40
+ @indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) }
41
+ val.join
42
+ end
43
+ end
44
+
45
+ def self.query(visitor, ast)
46
+ Query.new visitor.accept(ast, Arel::Collectors::SQLString.new).value
47
+ end
48
+
49
+ def self.partial_query(visitor, ast, collector)
50
+ collected = visitor.accept(ast, collector).value
51
+ PartialQuery.new collected
52
+ end
53
+
54
+ class Params
55
+ def bind; Substitute.new; end
20
56
  end
21
57
 
22
- def execute
23
- @relation.dup.to_a
58
+ class BindMap
59
+ def initialize(bind_values)
60
+ @indexes = []
61
+ @bind_values = bind_values
62
+
63
+ bind_values.each_with_index do |(_, value), i|
64
+ if Substitute === value
65
+ @indexes << i
66
+ end
67
+ end
68
+ end
69
+
70
+ def bind(values)
71
+ bvs = @bind_values.map { |pair| pair.dup }
72
+ @indexes.each_with_index { |offset,i| bvs[offset][1] = values[i] }
73
+ bvs
74
+ end
75
+ end
76
+
77
+ attr_reader :bind_map, :query_builder
78
+
79
+ def self.create(connection, block = Proc.new)
80
+ relation = block.call Params.new
81
+ bind_map = BindMap.new relation.bind_values
82
+ query_builder = connection.cacheable_query relation.arel
83
+ new query_builder, bind_map
84
+ end
85
+
86
+ def initialize(query_builder, bind_map)
87
+ @query_builder = query_builder
88
+ @bind_map = bind_map
89
+ end
90
+
91
+ def execute(params, klass, connection)
92
+ bind_values = bind_map.bind params
93
+
94
+ sql = query_builder.sql_for bind_values, connection
95
+
96
+ klass.find_by_sql sql, bind_values
24
97
  end
98
+ alias :call :execute
25
99
  end
26
100
  end
@@ -99,7 +99,7 @@ module ActiveRecord
99
99
  self.local_stored_attributes[store_attribute] |= keys
100
100
  end
101
101
 
102
- def _store_accessors_module
102
+ def _store_accessors_module # :nodoc:
103
103
  @_store_accessors_module ||= begin
104
104
  mod = Module.new
105
105
  include mod
@@ -129,10 +129,10 @@ module ActiveRecord
129
129
 
130
130
  private
131
131
  def store_accessor_for(store_attribute)
132
- @column_types[store_attribute.to_s].accessor
132
+ type_for_attribute(store_attribute.to_s).accessor
133
133
  end
134
134
 
135
- class HashAccessor
135
+ class HashAccessor # :nodoc:
136
136
  def self.read(object, attribute, key)
137
137
  prepare(object, attribute)
138
138
  object.public_send(attribute)[key]
@@ -151,7 +151,7 @@ module ActiveRecord
151
151
  end
152
152
  end
153
153
 
154
- class StringKeyedHashAccessor < HashAccessor
154
+ class StringKeyedHashAccessor < HashAccessor # :nodoc:
155
155
  def self.read(object, attribute, key)
156
156
  super object, attribute, key.to_s
157
157
  end
@@ -161,7 +161,7 @@ module ActiveRecord
161
161
  end
162
162
  end
163
163
 
164
- class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor
164
+ class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor # :nodoc:
165
165
  def self.prepare(object, store_attribute)
166
166
  attribute = object.send(store_attribute)
167
167
  unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess)
@@ -6,7 +6,7 @@ module ActiveRecord
6
6
  # <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates
7
7
  # logic behind common tasks used to manage database and migrations.
8
8
  #
9
- # The tasks defined here are used in rake tasks provided by Active Record.
9
+ # The tasks defined here are used with Rake tasks provided by Active Record.
10
10
  #
11
11
  # In order to use DatabaseTasks, a few config values need to be set. All the needed
12
12
  # config values are set by Rails already, so it's necessary to do it only if you
@@ -14,7 +14,6 @@ module ActiveRecord
14
14
  # (in such case after configuring the database tasks, you can also use the rake tasks
15
15
  # defined in Active Record).
16
16
  #
17
- #
18
17
  # The possible config values are:
19
18
  #
20
19
  # * +env+: current environment (like Rails.env).
@@ -28,7 +27,7 @@ module ActiveRecord
28
27
  # Example usage of +DatabaseTasks+ outside Rails could look as such:
29
28
  #
30
29
  # include ActiveRecord::Tasks
31
- # DatabaseTasks.database_configuration = YAML.load(File.read('my_database_config.yml'))
30
+ # DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
32
31
  # DatabaseTasks.db_dir = 'db'
33
32
  # # other settings...
34
33
  #
@@ -59,7 +58,11 @@ module ActiveRecord
59
58
  end
60
59
 
61
60
  def fixtures_path
62
- @fixtures_path ||= File.join(root, 'test', 'fixtures')
61
+ @fixtures_path ||= if ENV['FIXTURES_PATH']
62
+ File.join(root, ENV['FIXTURES_PATH'])
63
+ else
64
+ File.join(root, 'test', 'fixtures')
65
+ end
63
66
  end
64
67
 
65
68
  def root
@@ -107,6 +110,8 @@ module ActiveRecord
107
110
  def drop(*arguments)
108
111
  configuration = arguments.first
109
112
  class_for_adapter(configuration['adapter']).new(*arguments).drop
113
+ rescue ActiveRecord::NoDatabaseError
114
+ $stderr.puts "Database '#{configuration['database']}' does not exist"
110
115
  rescue Exception => error
111
116
  $stderr.puts error, *(error.backtrace)
112
117
  $stderr.puts "Couldn't drop #{configuration['database']}"
@@ -122,6 +127,16 @@ module ActiveRecord
122
127
  }
123
128
  end
124
129
 
130
+ def migrate
131
+ verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
132
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
133
+ scope = ENV['SCOPE']
134
+ Migration.verbose = verbose
135
+ Migrator.migrate(Migrator.migrations_paths, version) do |migration|
136
+ scope.blank? || scope == migration.scope
137
+ end
138
+ end
139
+
125
140
  def charset_current(environment = env)
126
141
  charset ActiveRecord::Base.configurations[environment]
127
142
  end
@@ -144,6 +159,18 @@ module ActiveRecord
144
159
  class_for_adapter(configuration['adapter']).new(configuration).purge
145
160
  end
146
161
 
162
+ def purge_all
163
+ each_local_configuration { |configuration|
164
+ purge configuration
165
+ }
166
+ end
167
+
168
+ def purge_current(environment = env)
169
+ each_current_configuration(environment) { |configuration|
170
+ purge configuration
171
+ }
172
+ end
173
+
147
174
  def structure_dump(*arguments)
148
175
  configuration = arguments.first
149
176
  filename = arguments.delete_at 1
@@ -157,6 +184,10 @@ module ActiveRecord
157
184
  end
158
185
 
159
186
  def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
187
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
188
+ This method will act on a specific connection in the future.
189
+ To act on the current connection, use `load_schema_current` instead.
190
+ MESSAGE
160
191
  load_schema_current(format, file)
161
192
  end
162
193
 
@@ -167,11 +198,13 @@ module ActiveRecord
167
198
  when :ruby
168
199
  file ||= File.join(db_dir, "schema.rb")
169
200
  check_schema_file(file)
201
+ purge(configuration)
170
202
  ActiveRecord::Base.establish_connection(configuration)
171
203
  load(file)
172
204
  when :sql
173
205
  file ||= File.join(db_dir, "structure.sql")
174
206
  check_schema_file(file)
207
+ purge(configuration)
175
208
  structure_load(configuration, file)
176
209
  else
177
210
  raise ArgumentError, "unknown format #{format.inspect}"
@@ -182,7 +215,6 @@ module ActiveRecord
182
215
  each_current_configuration(environment) { |configuration|
183
216
  load_schema_for configuration, format, file
184
217
  }
185
- ActiveRecord::Base.establish_connection(environment.to_sym)
186
218
  end
187
219
 
188
220
  def check_schema_file(filename)
@@ -124,26 +124,20 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
124
124
  end
125
125
 
126
126
  def root_password
127
- $stdout.print "Please provide the root password for your mysql installation\n>"
127
+ $stdout.print "Please provide the root password for your MySQL installation\n>"
128
128
  $stdin.gets.strip
129
129
  end
130
130
 
131
131
  def prepare_command_options(command)
132
- args = {
133
- 'host' => '--host',
134
- 'port' => '--port',
135
- 'socket' => '--socket',
136
- 'username' => '--user',
137
- 'password' => '--password',
138
- 'encoding' => '--default-character-set',
139
- 'sslca' => '--ssl-ca',
140
- 'sslcert' => '--ssl-cert',
141
- 'sslcapath' => '--ssl-capath',
142
- 'sslcipher' => '--ssl-cipher',
143
- 'sslkey' => '--ssl-key'
144
- }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
145
-
146
- [command, *args]
132
+ args = [command]
133
+ args.concat(['--user', configuration['username']]) if configuration['username']
134
+ args << "--password=#{configuration['password']}" if configuration['password']
135
+ args.concat(['--default-character-set', configuration['encoding']]) if configuration['encoding']
136
+ configuration.slice('host', 'port', 'socket').each do |k, v|
137
+ args.concat([ "--#{k}", v.to_s ]) if v
138
+ end
139
+
140
+ args
147
141
  end
148
142
  end
149
143
  end
@@ -51,10 +51,10 @@ module ActiveRecord
51
51
  search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ")
52
52
  end
53
53
 
54
- command = "pg_dump -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}"
54
+ command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}"
55
55
  raise 'Error dumping database' unless Kernel.system(command)
56
56
 
57
- File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" }
57
+ File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
58
58
  end
59
59
 
60
60
  def structure_load(filename)