activerecord 4.0.0.beta1 → 4.0.0.rc1

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +573 -30
  3. data/README.rdoc +3 -3
  4. data/lib/active_record.rb +8 -2
  5. data/lib/active_record/associations.rb +16 -9
  6. data/lib/active_record/associations/association.rb +8 -6
  7. data/lib/active_record/associations/association_scope.rb +2 -1
  8. data/lib/active_record/associations/belongs_to_association.rb +2 -2
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  10. data/lib/active_record/associations/builder/belongs_to.rb +37 -5
  11. data/lib/active_record/associations/collection_association.rb +38 -14
  12. data/lib/active_record/associations/collection_proxy.rb +18 -15
  13. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +3 -3
  14. data/lib/active_record/associations/has_many_association.rb +4 -3
  15. data/lib/active_record/associations/has_many_through_association.rb +1 -1
  16. data/lib/active_record/associations/has_one_association.rb +1 -1
  17. data/lib/active_record/associations/join_dependency.rb +29 -8
  18. data/lib/active_record/associations/join_dependency/join_association.rb +26 -6
  19. data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
  20. data/lib/active_record/associations/join_dependency/join_part.rb +6 -6
  21. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
  22. data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
  23. data/lib/active_record/associations/through_association.rb +1 -1
  24. data/lib/active_record/attribute_assignment.rb +5 -5
  25. data/lib/active_record/attribute_methods.rb +20 -5
  26. data/lib/active_record/attribute_methods/dirty.rb +5 -1
  27. data/lib/active_record/attribute_methods/primary_key.rb +1 -1
  28. data/lib/active_record/attribute_methods/serialization.rb +9 -2
  29. data/lib/active_record/autosave_association.rb +19 -5
  30. data/lib/active_record/base.rb +3 -3
  31. data/lib/active_record/callbacks.rb +1 -1
  32. data/lib/active_record/coders/yaml_column.rb +8 -13
  33. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +3 -9
  34. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -1
  35. data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -1
  36. data/lib/active_record/connection_adapters/abstract/quoting.rb +2 -8
  37. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +60 -61
  38. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +13 -2
  39. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -153
  40. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract_adapter.rb +92 -1
  42. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +55 -29
  43. data/lib/active_record/connection_adapters/column.rb +4 -4
  44. data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
  45. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -3
  46. data/lib/active_record/connection_adapters/mysql_adapter.rb +5 -5
  47. data/lib/active_record/connection_adapters/postgresql/cast.rb +22 -2
  48. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -6
  49. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -13
  50. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +50 -9
  51. data/lib/active_record/connection_adapters/postgresql_adapter.rb +53 -24
  52. data/lib/active_record/connection_adapters/schema_cache.rb +35 -7
  53. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +13 -5
  54. data/lib/active_record/connection_handling.rb +7 -7
  55. data/lib/active_record/core.rb +43 -8
  56. data/lib/active_record/counter_cache.rb +2 -1
  57. data/lib/active_record/errors.rb +11 -10
  58. data/lib/active_record/explain.rb +9 -7
  59. data/lib/active_record/explain_registry.rb +30 -0
  60. data/lib/active_record/explain_subscriber.rb +3 -2
  61. data/lib/active_record/fixture_set/file.rb +1 -2
  62. data/lib/active_record/fixtures.rb +13 -7
  63. data/lib/active_record/inheritance.rb +12 -4
  64. data/lib/active_record/integration.rb +3 -3
  65. data/lib/active_record/locking/optimistic.rb +2 -2
  66. data/lib/active_record/log_subscriber.rb +2 -2
  67. data/lib/active_record/migration.rb +69 -21
  68. data/lib/active_record/model_schema.rb +1 -1
  69. data/lib/active_record/nested_attributes.rb +98 -46
  70. data/lib/active_record/persistence.rb +3 -3
  71. data/lib/active_record/querying.rb +1 -1
  72. data/lib/active_record/railtie.rb +18 -4
  73. data/lib/active_record/railties/console_sandbox.rb +3 -2
  74. data/lib/active_record/railties/controller_runtime.rb +2 -1
  75. data/lib/active_record/railties/databases.rake +38 -80
  76. data/lib/active_record/reflection.rb +36 -3
  77. data/lib/active_record/relation.rb +18 -8
  78. data/lib/active_record/relation/calculations.rb +10 -5
  79. data/lib/active_record/relation/delegation.rb +3 -5
  80. data/lib/active_record/relation/finder_methods.rb +27 -14
  81. data/lib/active_record/relation/merger.rb +30 -2
  82. data/lib/active_record/relation/predicate_builder.rb +1 -6
  83. data/lib/active_record/relation/query_methods.rb +113 -16
  84. data/lib/active_record/runtime_registry.rb +17 -0
  85. data/lib/active_record/schema_dumper.rb +5 -1
  86. data/lib/active_record/schema_migration.rb +8 -5
  87. data/lib/active_record/scoping.rb +56 -2
  88. data/lib/active_record/scoping/default.rb +12 -11
  89. data/lib/active_record/scoping/named.rb +7 -3
  90. data/lib/active_record/serialization.rb +1 -1
  91. data/lib/active_record/statement_cache.rb +26 -0
  92. data/lib/active_record/tasks/database_tasks.rb +55 -10
  93. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  94. data/lib/active_record/tasks/mysql_database_tasks.rb +7 -2
  95. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  96. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  97. data/lib/active_record/timestamp.rb +6 -0
  98. data/lib/active_record/transactions.rb +7 -3
  99. data/lib/active_record/validations.rb +1 -2
  100. data/lib/active_record/validations/uniqueness.rb +7 -3
  101. data/lib/active_record/version.rb +7 -6
  102. data/lib/rails/generators/active_record/migration/migration_generator.rb +9 -2
  103. data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
  104. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  105. data/lib/rails/generators/active_record/model/templates/model.rb +4 -1
  106. metadata +17 -12
  107. data/examples/associations.png +0 -0
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  # Person.count(:all)
12
12
  # # => performs a COUNT(*) (:all is an alias for '*')
13
13
  #
14
- # Person.count(:age, distinct: true)
14
+ # Person.distinct.count(:age)
15
15
  # # => counts the number of different age values
16
16
  #
17
17
  # If +count+ is used with +group+, it returns a Hash whose keys represent the aggregated column,
@@ -82,7 +82,7 @@ module ActiveRecord
82
82
  # puts values["Drake"]
83
83
  # # => 43
84
84
  #
85
- # drake = Family.find_by_last_name('Drake')
85
+ # drake = Family.find_by(last_name: 'Drake')
86
86
  # values = Person.group(:family).maximum(:age) # Person belongs_to :family
87
87
  # puts values[drake]
88
88
  # # => 43
@@ -135,7 +135,7 @@ module ActiveRecord
135
135
  # # SELECT people.id, people.name FROM people
136
136
  # # => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
137
137
  #
138
- # Person.uniq.pluck(:role)
138
+ # Person.pluck('DISTINCT role')
139
139
  # # SELECT DISTINCT role FROM people
140
140
  # # => ['admin', 'member', 'guest']
141
141
  #
@@ -198,8 +198,13 @@ module ActiveRecord
198
198
  def perform_calculation(operation, column_name, options = {})
199
199
  operation = operation.to_s.downcase
200
200
 
201
- # If #count is used in conjuction with #uniq it is considered distinct. (eg. relation.uniq.count)
202
- distinct = options[:distinct] || self.uniq_value
201
+ # If #count is used with #distinct / #uniq it is considered distinct. (eg. relation.distinct.count)
202
+ distinct = self.distinct_value
203
+ if options.has_key?(:distinct)
204
+ ActiveSupport::Deprecation.warn "The :distinct option for `Relation#count` is deprecated. " \
205
+ "Please use `Relation#distinct` instead. (eg. `relation.distinct.count`)"
206
+ distinct = options[:distinct]
207
+ end
203
208
 
204
209
  if operation == "count"
205
210
  column_name ||= (select_for_count || :all)
@@ -37,11 +37,9 @@ module ActiveRecord
37
37
  end
38
38
  RUBY
39
39
  else
40
- module_eval <<-RUBY, __FILE__, __LINE__ + 1
41
- def #{method}(*args, &block)
42
- scoping { @klass.send(#{method.inspect}, *args, &block) }
43
- end
44
- RUBY
40
+ define_method method do |*args, &block|
41
+ scoping { @klass.send(method, *args, &block) }
42
+ end
45
43
  end
46
44
  end
47
45
  end
@@ -37,7 +37,7 @@ module ActiveRecord
37
37
  end
38
38
 
39
39
  # Finds the first record matching the specified conditions. There
40
- # is no implied ording so if order matters, you should specify it
40
+ # is no implied ordering so if order matters, you should specify it
41
41
  # yourself.
42
42
  #
43
43
  # If no record is found, returns <tt>nil</tt>.
@@ -130,8 +130,8 @@ module ActiveRecord
130
130
  last or raise RecordNotFound
131
131
  end
132
132
 
133
- # Returns +true+ if a record exists in the table that matches the +id+ or
134
- # conditions given, or +false+ otherwise. The argument can take six forms:
133
+ # Returns truthy if a record exists in the table that matches the +id+ or
134
+ # conditions given, or falsy otherwise. The argument can take six forms:
135
135
  #
136
136
  # * Integer - Finds the record with this primary key.
137
137
  # * String - Finds the record with a primary key corresponding to this
@@ -176,6 +176,28 @@ module ActiveRecord
176
176
  false
177
177
  end
178
178
 
179
+ # This method is called whenever no records are found with either a single
180
+ # id or multiple ids and raises a +ActiveRecord::RecordNotFound+ exception.
181
+ #
182
+ # The error message is different depending on whether a single id or
183
+ # multiple ids are provided. If multiple ids are provided, then the number
184
+ # of results obtained should be provided in the +result_size+ argument and
185
+ # the expected number of results should be provided in the +expected_size+
186
+ # argument.
187
+ def raise_record_not_found_exception!(ids, result_size, expected_size) #:nodoc:
188
+ conditions = arel.where_sql
189
+ conditions = " [#{conditions}]" if conditions
190
+
191
+ if Array(ids).size == 1
192
+ error = "Couldn't find #{@klass.name} with #{primary_key}=#{ids}#{conditions}"
193
+ else
194
+ error = "Couldn't find all #{@klass.name.pluralize} with IDs "
195
+ error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})"
196
+ end
197
+
198
+ raise RecordNotFound, error
199
+ end
200
+
179
201
  protected
180
202
 
181
203
  def find_with_associations
@@ -259,11 +281,7 @@ module ActiveRecord
259
281
  relation.bind_values += [[column, id]]
260
282
  record = relation.take
261
283
 
262
- unless record
263
- conditions = arel.where_sql
264
- conditions = " [#{conditions}]" if conditions
265
- raise RecordNotFound, "Couldn't find #{@klass.name} with #{primary_key}=#{id}#{conditions}"
266
- end
284
+ raise_record_not_found_exception!(id, 0, 1) unless record
267
285
 
268
286
  record
269
287
  end
@@ -286,12 +304,7 @@ module ActiveRecord
286
304
  if result.size == expected_size
287
305
  result
288
306
  else
289
- conditions = arel.where_sql
290
- conditions = " [#{conditions}]" if conditions
291
-
292
- error = "Couldn't find all #{@klass.name.pluralize} with IDs "
293
- error << "(#{ids.join(", ")})#{conditions} (found #{result.size} results, but was looking for #{expected_size})"
294
- raise RecordNotFound, error
307
+ raise_record_not_found_exception!(ids, result.size, expected_size)
295
308
  end
296
309
  end
297
310
 
@@ -39,7 +39,7 @@ module ActiveRecord
39
39
  end
40
40
 
41
41
  class Merger # :nodoc:
42
- attr_reader :relation, :values
42
+ attr_reader :relation, :values, :other
43
43
 
44
44
  def initialize(relation, other)
45
45
  if other.default_scoped? && other.klass != relation.klass
@@ -48,11 +48,12 @@ module ActiveRecord
48
48
 
49
49
  @relation = relation
50
50
  @values = other.values
51
+ @other = other
51
52
  end
52
53
 
53
54
  NORMAL_VALUES = Relation::SINGLE_VALUE_METHODS +
54
55
  Relation::MULTI_VALUE_METHODS -
55
- [:where, :order, :bind, :reverse_order, :lock, :create_with, :reordering, :from] # :nodoc:
56
+ [:joins, :where, :order, :bind, :reverse_order, :lock, :create_with, :reordering, :from] # :nodoc:
56
57
 
57
58
  def normal_values
58
59
  NORMAL_VALUES
@@ -66,12 +67,39 @@ module ActiveRecord
66
67
 
67
68
  merge_multi_values
68
69
  merge_single_values
70
+ merge_joins
69
71
 
70
72
  relation
71
73
  end
72
74
 
73
75
  private
74
76
 
77
+ def merge_joins
78
+ return if values[:joins].blank?
79
+
80
+ if other.klass == relation.klass
81
+ relation.joins!(*values[:joins])
82
+ else
83
+ joins_dependency, rest = values[:joins].partition do |join|
84
+ case join
85
+ when Hash, Symbol, Array
86
+ true
87
+ else
88
+ false
89
+ end
90
+ end
91
+
92
+ join_dependency = ActiveRecord::Associations::JoinDependency.new(other.klass,
93
+ joins_dependency,
94
+ [])
95
+ relation.joins! rest
96
+
97
+ join_dependency.join_associations.each do |association|
98
+ @relation = association.join_relation(relation)
99
+ end
100
+ end
101
+ end
102
+
75
103
  def merge_multi_values
76
104
  relation.where_values = merged_wheres
77
105
  relation.bind_values = merged_binds
@@ -48,7 +48,7 @@ module ActiveRecord
48
48
  column = reflection.foreign_key
49
49
  end
50
50
 
51
- queries << build(table[column.to_sym], value)
51
+ queries << build(table[column], value)
52
52
  queries
53
53
  end
54
54
 
@@ -98,11 +98,6 @@ module ActiveRecord
98
98
  when Class
99
99
  # FIXME: I think we need to deprecate this behavior
100
100
  attribute.eq(value.name)
101
- when Integer, ActiveSupport::Duration
102
- # Arel treats integers as literals, but they should be quoted when compared with strings
103
- table = attribute.relation
104
- column = table.engine.connection.schema_cache.columns_hash(table.name)[attribute.name.to_s]
105
- attribute.eq(Arel::Nodes::SqlLiteral.new(table.engine.connection.quote(value, column)))
106
101
  else
107
102
  attribute.eq(value)
108
103
  end
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  # WhereChain objects act as placeholder for queries in which #where does not have any parameter.
8
- # In this case, #where must be chained with either #not, #like, or #not_like to return a new relation.
8
+ # In this case, #where must be chained with #not to return a new relation.
9
9
  class WhereChain
10
10
  def initialize(scope)
11
11
  @scope = scope
@@ -34,7 +34,6 @@ module ActiveRecord
34
34
  #
35
35
  # User.where.not(name: "Jon", role: "admin")
36
36
  # # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
37
- #
38
37
  def not(opts, *rest)
39
38
  where_value = @scope.send(:build_where, opts, rest).map do |rel|
40
39
  case rel
@@ -285,6 +284,11 @@ module ActiveRecord
285
284
  references.map! { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 }.compact!
286
285
  references!(references) if references.any?
287
286
 
287
+ # if a symbol is given we prepend the quoted table name
288
+ args = args.map { |arg|
289
+ arg.is_a?(Symbol) ? "#{quoted_table_name}.#{arg} ASC" : arg
290
+ }
291
+
288
292
  self.order_values = args + self.order_values
289
293
  self
290
294
  end
@@ -312,6 +316,67 @@ module ActiveRecord
312
316
  self
313
317
  end
314
318
 
319
+ VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
320
+ :limit, :offset, :joins, :includes, :from,
321
+ :readonly, :having])
322
+
323
+ # Removes an unwanted relation that is already defined on a chain of relations.
324
+ # This is useful when passing around chains of relations and would like to
325
+ # modify the relations without reconstructing the entire chain.
326
+ #
327
+ # User.order('email DESC').unscope(:order) == User.all
328
+ #
329
+ # The method arguments are symbols which correspond to the names of the methods
330
+ # which should be unscoped. The valid arguments are given in VALID_UNSCOPING_VALUES.
331
+ # The method can also be called with multiple arguments. For example:
332
+ #
333
+ # User.order('email DESC').select('id').where(name: "John")
334
+ # .unscope(:order, :select, :where) == User.all
335
+ #
336
+ # One can additionally pass a hash as an argument to unscope specific :where values.
337
+ # This is done by passing a hash with a single key-value pair. The key should be
338
+ # :where and the value should be the where value to unscope. For example:
339
+ #
340
+ # User.where(name: "John", active: true).unscope(where: :name)
341
+ # == User.where(active: true)
342
+ #
343
+ # Note that this method is more generalized than ActiveRecord::SpawnMethods#except
344
+ # because #except will only affect a particular relation's values. It won't wipe
345
+ # the order, grouping, etc. when that relation is merged. For example:
346
+ #
347
+ # Post.comments.except(:order)
348
+ #
349
+ # will still have an order if it comes from the default_scope on Comment.
350
+ def unscope(*args)
351
+ check_if_method_has_arguments!("unscope", args)
352
+ spawn.unscope!(*args)
353
+ end
354
+
355
+ def unscope!(*args) # :nodoc:
356
+ args.flatten!
357
+
358
+ args.each do |scope|
359
+ case scope
360
+ when Symbol
361
+ symbol_unscoping(scope)
362
+ when Hash
363
+ scope.each do |key, target_value|
364
+ if key != :where
365
+ raise ArgumentError, "Hash arguments in .unscope(*args) must have :where as the key."
366
+ end
367
+
368
+ Array(target_value).each do |val|
369
+ where_unscoping(val)
370
+ end
371
+ end
372
+ else
373
+ raise ArgumentError, "Unrecognized scoping: #{args.inspect}. Use .unscope(where: :attribute_name) or .unscope(:order), for example."
374
+ end
375
+ end
376
+
377
+ self
378
+ end
379
+
315
380
  # Performs a joins on +args+:
316
381
  #
317
382
  # User.joins(:posts)
@@ -486,7 +551,6 @@ module ActiveRecord
486
551
  # Order.having('SUM(price) > 30').group('user_id')
487
552
  def having(opts, *rest)
488
553
  opts.blank? ? self : spawn.having!(opts, *rest)
489
- spawn.having!(opts, *rest)
490
554
  end
491
555
 
492
556
  def having!(opts, *rest) # :nodoc:
@@ -548,7 +612,7 @@ module ActiveRecord
548
612
  #
549
613
  # The returned <tt>ActiveRecord::NullRelation</tt> inherits from Relation and implements the
550
614
  # Null Object pattern. It is an object with defined null behavior and always returns an empty
551
- # array of records without quering the database.
615
+ # array of records without querying the database.
552
616
  #
553
617
  # Any subsequent condition chained to the returned relation will continue
554
618
  # generating an empty relation and will not fire any query to the database.
@@ -644,20 +708,22 @@ module ActiveRecord
644
708
  # User.select(:name)
645
709
  # # => Might return two records with the same name
646
710
  #
647
- # User.select(:name).uniq
648
- # # => Returns 1 record per unique name
711
+ # User.select(:name).distinct
712
+ # # => Returns 1 record per distinct name
649
713
  #
650
- # User.select(:name).uniq.uniq(false)
714
+ # User.select(:name).distinct.distinct(false)
651
715
  # # => You can also remove the uniqueness
652
- def uniq(value = true)
653
- spawn.uniq!(value)
716
+ def distinct(value = true)
717
+ spawn.distinct!(value)
654
718
  end
719
+ alias uniq distinct
655
720
 
656
- # Like #uniq, but modifies relation in place.
657
- def uniq!(value = true) # :nodoc:
658
- self.uniq_value = value
721
+ # Like #distinct, but modifies relation in place.
722
+ def distinct!(value = true) # :nodoc:
723
+ self.distinct_value = value
659
724
  self
660
725
  end
726
+ alias uniq! distinct!
661
727
 
662
728
  # Used to extend a scope with additional methods, either through
663
729
  # a module or through a block provided.
@@ -748,7 +814,7 @@ module ActiveRecord
748
814
 
749
815
  build_select(arel, select_values.uniq)
750
816
 
751
- arel.distinct(uniq_value)
817
+ arel.distinct(distinct_value)
752
818
  arel.from(build_from) if from_value
753
819
  arel.lock(lock_value) if lock_value
754
820
 
@@ -757,6 +823,39 @@ module ActiveRecord
757
823
 
758
824
  private
759
825
 
826
+ def symbol_unscoping(scope)
827
+ if !VALID_UNSCOPING_VALUES.include?(scope)
828
+ raise ArgumentError, "Called unscope() with invalid unscoping argument ':#{scope}'. Valid arguments are :#{VALID_UNSCOPING_VALUES.to_a.join(", :")}."
829
+ end
830
+
831
+ single_val_method = Relation::SINGLE_VALUE_METHODS.include?(scope)
832
+ unscope_code = :"#{scope}_value#{'s' unless single_val_method}="
833
+
834
+ case scope
835
+ when :order
836
+ self.send(:reverse_order_value=, false)
837
+ result = []
838
+ else
839
+ result = [] unless single_val_method
840
+ end
841
+
842
+ self.send(unscope_code, result)
843
+ end
844
+
845
+ def where_unscoping(target_value)
846
+ target_value_sym = target_value.to_sym
847
+
848
+ where_values.reject! do |rel|
849
+ case rel
850
+ when Arel::Nodes::In, Arel::Nodes::Equality
851
+ subrelation = (rel.left.kind_of?(Arel::Attributes::Attribute) ? rel.left : rel.right)
852
+ subrelation.name.to_sym == target_value_sym
853
+ else
854
+ raise "unscope(where: #{target_value.inspect}) failed: unscoping #{rel.class} is unimplemented."
855
+ end
856
+ end
857
+ end
858
+
760
859
  def custom_join_ast(table, joins)
761
860
  joins = joins.reject { |join| join.blank? }
762
861
 
@@ -833,9 +932,7 @@ module ActiveRecord
833
932
  association_joins = buckets[:association_join] || []
834
933
  stashed_association_joins = buckets[:stashed_join] || []
835
934
  join_nodes = (buckets[:join_node] || []).uniq
836
- string_joins = (buckets[:string_join] || []).map { |x|
837
- x.strip
838
- }.uniq
935
+ string_joins = (buckets[:string_join] || []).map { |x| x.strip }.uniq
839
936
 
840
937
  join_list = join_nodes + custom_join_ast(manager, string_joins)
841
938
 
@@ -0,0 +1,17 @@
1
+ require 'active_support/per_thread_registry'
2
+
3
+ module ActiveRecord
4
+ # This is a thread locals registry for Active Record. For example:
5
+ #
6
+ # ActiveRecord::RuntimeRegistry.connection_handler
7
+ #
8
+ # returns the connection handler local to the current thread.
9
+ #
10
+ # See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
11
+ # for further details.
12
+ class RuntimeRegistry # :nodoc:
13
+ extend ActiveSupport::PerThreadRegistry
14
+
15
+ attr_accessor :connection_handler, :sql_runtime, :connection_id
16
+ end
17
+ end
@@ -118,7 +118,7 @@ HEADER
118
118
 
119
119
  # then dump all non-primary key columns
120
120
  column_specs = columns.map do |column|
121
- raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
121
+ raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
122
122
  next if column.name == pk
123
123
  @connection.column_spec(column, @types)
124
124
  end.compact
@@ -185,6 +185,10 @@ HEADER
185
185
 
186
186
  statement_parts << ('where: ' + index.where.inspect) if index.where
187
187
 
188
+ statement_parts << ('using: ' + index.using.inspect) if index.using
189
+
190
+ statement_parts << ('type: ' + index.type.inspect) if index.type
191
+
188
192
  ' ' + statement_parts.join(', ')
189
193
  end
190
194