activerecord 3.2.22.5 → 4.2.11.3

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 (236) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1632 -609
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +37 -41
  5. data/examples/performance.rb +31 -19
  6. data/examples/simple.rb +4 -4
  7. data/lib/active_record/aggregations.rb +56 -42
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -36
  10. data/lib/active_record/associations/association.rb +73 -55
  11. data/lib/active_record/associations/association_scope.rb +143 -82
  12. data/lib/active_record/associations/belongs_to_association.rb +65 -25
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  14. data/lib/active_record/associations/builder/association.rb +125 -31
  15. data/lib/active_record/associations/builder/belongs_to.rb +89 -61
  16. data/lib/active_record/associations/builder/collection_association.rb +69 -49
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +113 -42
  18. data/lib/active_record/associations/builder/has_many.rb +8 -64
  19. data/lib/active_record/associations/builder/has_one.rb +12 -51
  20. data/lib/active_record/associations/builder/singular_association.rb +23 -17
  21. data/lib/active_record/associations/collection_association.rb +251 -177
  22. data/lib/active_record/associations/collection_proxy.rb +963 -63
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +113 -22
  25. data/lib/active_record/associations/has_many_through_association.rb +99 -39
  26. data/lib/active_record/associations/has_one_association.rb +43 -20
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +76 -107
  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 +230 -156
  32. data/lib/active_record/associations/preloader/association.rb +96 -55
  33. data/lib/active_record/associations/preloader/collection_association.rb +3 -3
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +62 -33
  38. data/lib/active_record/associations/preloader.rb +101 -79
  39. data/lib/active_record/associations/singular_association.rb +29 -13
  40. data/lib/active_record/associations/through_association.rb +30 -16
  41. data/lib/active_record/associations.rb +463 -345
  42. data/lib/active_record/attribute.rb +163 -0
  43. data/lib/active_record/attribute_assignment.rb +142 -151
  44. data/lib/active_record/attribute_decorators.rb +66 -0
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  46. data/lib/active_record/attribute_methods/dirty.rb +137 -57
  47. data/lib/active_record/attribute_methods/primary_key.rb +50 -36
  48. data/lib/active_record/attribute_methods/query.rb +5 -4
  49. data/lib/active_record/attribute_methods/read.rb +73 -106
  50. data/lib/active_record/attribute_methods/serialization.rb +44 -94
  51. data/lib/active_record/attribute_methods/time_zone_conversion.rb +49 -45
  52. data/lib/active_record/attribute_methods/write.rb +57 -44
  53. data/lib/active_record/attribute_methods.rb +301 -141
  54. data/lib/active_record/attribute_set/builder.rb +106 -0
  55. data/lib/active_record/attribute_set.rb +81 -0
  56. data/lib/active_record/attributes.rb +147 -0
  57. data/lib/active_record/autosave_association.rb +246 -217
  58. data/lib/active_record/base.rb +70 -474
  59. data/lib/active_record/callbacks.rb +66 -28
  60. data/lib/active_record/coders/json.rb +13 -0
  61. data/lib/active_record/coders/yaml_column.rb +18 -21
  62. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +396 -219
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -164
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +29 -24
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -55
  67. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  68. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
  69. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +261 -169
  70. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +707 -259
  72. data/lib/active_record/connection_adapters/abstract/transaction.rb +215 -0
  73. data/lib/active_record/connection_adapters/abstract_adapter.rb +298 -89
  74. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +466 -196
  75. data/lib/active_record/connection_adapters/column.rb +31 -245
  76. data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +45 -57
  78. data/lib/active_record/connection_adapters/mysql_adapter.rb +180 -123
  79. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
  80. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  81. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +596 -0
  112. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  113. data/lib/active_record/connection_adapters/postgresql_adapter.rb +430 -999
  114. data/lib/active_record/connection_adapters/schema_cache.rb +52 -27
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +579 -22
  116. data/lib/active_record/connection_handling.rb +132 -0
  117. data/lib/active_record/core.rb +579 -0
  118. data/lib/active_record/counter_cache.rb +157 -105
  119. data/lib/active_record/dynamic_matchers.rb +119 -63
  120. data/lib/active_record/enum.rb +197 -0
  121. data/lib/active_record/errors.rb +94 -36
  122. data/lib/active_record/explain.rb +15 -63
  123. data/lib/active_record/explain_registry.rb +30 -0
  124. data/lib/active_record/explain_subscriber.rb +9 -5
  125. data/lib/active_record/fixture_set/file.rb +56 -0
  126. data/lib/active_record/fixtures.rb +302 -215
  127. data/lib/active_record/gem_version.rb +15 -0
  128. data/lib/active_record/inheritance.rb +143 -70
  129. data/lib/active_record/integration.rb +65 -12
  130. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  131. data/lib/active_record/locale/en.yml +8 -1
  132. data/lib/active_record/locking/optimistic.rb +73 -52
  133. data/lib/active_record/locking/pessimistic.rb +5 -5
  134. data/lib/active_record/log_subscriber.rb +24 -21
  135. data/lib/active_record/migration/command_recorder.rb +124 -32
  136. data/lib/active_record/migration/join_table.rb +15 -0
  137. data/lib/active_record/migration.rb +511 -213
  138. data/lib/active_record/model_schema.rb +91 -117
  139. data/lib/active_record/nested_attributes.rb +184 -130
  140. data/lib/active_record/no_touching.rb +52 -0
  141. data/lib/active_record/null_relation.rb +81 -0
  142. data/lib/active_record/persistence.rb +276 -117
  143. data/lib/active_record/query_cache.rb +19 -37
  144. data/lib/active_record/querying.rb +28 -18
  145. data/lib/active_record/railtie.rb +73 -40
  146. data/lib/active_record/railties/console_sandbox.rb +3 -4
  147. data/lib/active_record/railties/controller_runtime.rb +4 -3
  148. data/lib/active_record/railties/databases.rake +141 -416
  149. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  150. data/lib/active_record/readonly_attributes.rb +1 -4
  151. data/lib/active_record/reflection.rb +513 -154
  152. data/lib/active_record/relation/batches.rb +91 -43
  153. data/lib/active_record/relation/calculations.rb +199 -161
  154. data/lib/active_record/relation/delegation.rb +116 -25
  155. data/lib/active_record/relation/finder_methods.rb +362 -248
  156. data/lib/active_record/relation/merger.rb +193 -0
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  158. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  159. data/lib/active_record/relation/predicate_builder.rb +135 -43
  160. data/lib/active_record/relation/query_methods.rb +928 -167
  161. data/lib/active_record/relation/spawn_methods.rb +48 -149
  162. data/lib/active_record/relation.rb +352 -207
  163. data/lib/active_record/result.rb +101 -10
  164. data/lib/active_record/runtime_registry.rb +22 -0
  165. data/lib/active_record/sanitization.rb +56 -59
  166. data/lib/active_record/schema.rb +19 -13
  167. data/lib/active_record/schema_dumper.rb +106 -63
  168. data/lib/active_record/schema_migration.rb +53 -0
  169. data/lib/active_record/scoping/default.rb +50 -57
  170. data/lib/active_record/scoping/named.rb +73 -109
  171. data/lib/active_record/scoping.rb +58 -123
  172. data/lib/active_record/serialization.rb +6 -2
  173. data/lib/active_record/serializers/xml_serializer.rb +12 -22
  174. data/lib/active_record/statement_cache.rb +111 -0
  175. data/lib/active_record/store.rb +168 -15
  176. data/lib/active_record/tasks/database_tasks.rb +299 -0
  177. data/lib/active_record/tasks/mysql_database_tasks.rb +159 -0
  178. data/lib/active_record/tasks/postgresql_database_tasks.rb +101 -0
  179. data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
  180. data/lib/active_record/timestamp.rb +23 -16
  181. data/lib/active_record/transactions.rb +125 -79
  182. data/lib/active_record/type/big_integer.rb +13 -0
  183. data/lib/active_record/type/binary.rb +50 -0
  184. data/lib/active_record/type/boolean.rb +31 -0
  185. data/lib/active_record/type/date.rb +50 -0
  186. data/lib/active_record/type/date_time.rb +54 -0
  187. data/lib/active_record/type/decimal.rb +64 -0
  188. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  189. data/lib/active_record/type/decorator.rb +14 -0
  190. data/lib/active_record/type/float.rb +19 -0
  191. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  192. data/lib/active_record/type/integer.rb +59 -0
  193. data/lib/active_record/type/mutable.rb +16 -0
  194. data/lib/active_record/type/numeric.rb +36 -0
  195. data/lib/active_record/type/serialized.rb +62 -0
  196. data/lib/active_record/type/string.rb +40 -0
  197. data/lib/active_record/type/text.rb +11 -0
  198. data/lib/active_record/type/time.rb +26 -0
  199. data/lib/active_record/type/time_value.rb +38 -0
  200. data/lib/active_record/type/type_map.rb +64 -0
  201. data/lib/active_record/type/unsigned_integer.rb +15 -0
  202. data/lib/active_record/type/value.rb +110 -0
  203. data/lib/active_record/type.rb +23 -0
  204. data/lib/active_record/validations/associated.rb +24 -16
  205. data/lib/active_record/validations/presence.rb +67 -0
  206. data/lib/active_record/validations/uniqueness.rb +123 -64
  207. data/lib/active_record/validations.rb +36 -29
  208. data/lib/active_record/version.rb +5 -7
  209. data/lib/active_record.rb +66 -46
  210. data/lib/rails/generators/active_record/migration/migration_generator.rb +53 -8
  211. data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +5 -1
  212. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  213. data/lib/rails/generators/active_record/migration.rb +11 -8
  214. data/lib/rails/generators/active_record/model/model_generator.rb +9 -4
  215. data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
  216. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  217. data/lib/rails/generators/active_record.rb +3 -11
  218. metadata +101 -45
  219. data/examples/associations.png +0 -0
  220. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  221. data/lib/active_record/associations/join_helper.rb +0 -55
  222. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  223. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  224. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  225. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  226. data/lib/active_record/dynamic_finder_match.rb +0 -68
  227. data/lib/active_record/dynamic_scope_match.rb +0 -23
  228. data/lib/active_record/fixtures/file.rb +0 -65
  229. data/lib/active_record/identity_map.rb +0 -162
  230. data/lib/active_record/observer.rb +0 -121
  231. data/lib/active_record/session_store.rb +0 -360
  232. data/lib/active_record/test_case.rb +0 -73
  233. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  234. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  235. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  236. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -3,36 +3,127 @@ module ActiveRecord
3
3
  # This class encapsulates a Result returned from calling +exec_query+ on any
4
4
  # database connection adapter. For example:
5
5
  #
6
- # x = ActiveRecord::Base.connection.exec_query('SELECT * FROM foo')
7
- # x # => #<ActiveRecord::Result:0xdeadbeef>
6
+ # result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
7
+ # result # => #<ActiveRecord::Result:0xdeadbeef>
8
+ #
9
+ # # Get the column names of the result:
10
+ # result.columns
11
+ # # => ["id", "title", "body"]
12
+ #
13
+ # # Get the record values of the result:
14
+ # result.rows
15
+ # # => [[1, "title_1", "body_1"],
16
+ # [2, "title_2", "body_2"],
17
+ # ...
18
+ # ]
19
+ #
20
+ # # Get an array of hashes representing the result (column => value):
21
+ # result.to_hash
22
+ # # => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
23
+ # {"id" => 2, "title" => "title_2", "body" => "body_2"},
24
+ # ...
25
+ # ]
26
+ #
27
+ # # ActiveRecord::Result also includes Enumerable.
28
+ # result.each do |row|
29
+ # puts row['title'] + " " + row['body']
30
+ # end
8
31
  class Result
9
32
  include Enumerable
10
33
 
11
- attr_reader :columns, :rows
34
+ IDENTITY_TYPE = Type::Value.new # :nodoc:
35
+
36
+ attr_reader :columns, :rows, :column_types
37
+
38
+ def initialize(columns, rows, column_types = {})
39
+ @columns = columns
40
+ @rows = rows
41
+ @hash_rows = nil
42
+ @column_types = column_types
43
+ end
12
44
 
13
- def initialize(columns, rows)
14
- @columns = columns
15
- @rows = rows
16
- @hash_rows = nil
45
+ def length
46
+ @rows.length
17
47
  end
18
48
 
19
49
  def each
20
- hash_rows.each { |row| yield row }
50
+ if block_given?
51
+ hash_rows.each { |row| yield row }
52
+ else
53
+ hash_rows.to_enum { @rows.size }
54
+ end
21
55
  end
22
56
 
23
57
  def to_hash
24
58
  hash_rows
25
59
  end
26
60
 
61
+ alias :map! :map
62
+ alias :collect! :map
63
+
64
+ # Returns true if there are no records.
65
+ def empty?
66
+ rows.empty?
67
+ end
68
+
69
+ def to_ary
70
+ hash_rows
71
+ end
72
+
73
+ def [](idx)
74
+ hash_rows[idx]
75
+ end
76
+
77
+ def last
78
+ hash_rows.last
79
+ end
80
+
81
+ def cast_values(type_overrides = {}) # :nodoc:
82
+ types = columns.map { |name| column_type(name, type_overrides) }
83
+ result = rows.map do |values|
84
+ types.zip(values).map { |type, value| type.type_cast_from_database(value) }
85
+ end
86
+
87
+ columns.one? ? result.map!(&:first) : result
88
+ end
89
+
90
+ def initialize_copy(other)
91
+ @columns = columns.dup
92
+ @rows = rows.dup
93
+ @column_types = column_types.dup
94
+ @hash_rows = nil
95
+ end
96
+
27
97
  private
98
+
99
+ def column_type(name, type_overrides = {})
100
+ type_overrides.fetch(name) do
101
+ column_types.fetch(name, IDENTITY_TYPE)
102
+ end
103
+ end
104
+
28
105
  def hash_rows
29
106
  @hash_rows ||=
30
107
  begin
31
108
  # We freeze the strings to prevent them getting duped when
32
- # used as keys in ActiveRecord::Model's @attributes hash
109
+ # used as keys in ActiveRecord::Base's @attributes hash
33
110
  columns = @columns.map { |c| c.dup.freeze }
34
111
  @rows.map { |row|
35
- Hash[columns.zip(row)]
112
+ # In the past we used Hash[columns.zip(row)]
113
+ # though elegant, the verbose way is much more efficient
114
+ # both time and memory wise cause it avoids a big array allocation
115
+ # this method is called a lot and needs to be micro optimised
116
+ hash = {}
117
+
118
+ index = 0
119
+ length = columns.length
120
+
121
+ while index < length
122
+ hash[columns[index]] = row[index]
123
+ index += 1
124
+ end
125
+
126
+ hash
36
127
  }
37
128
  end
38
129
  end
@@ -0,0 +1,22 @@
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
+
17
+ [:connection_handler, :sql_runtime, :connection_id].each do |val|
18
+ class_eval %{ def self.#{val}; instance.#{val}; end }, __FILE__, __LINE__
19
+ class_eval %{ def self.#{val}=(x); instance.#{val}=x; end }, __FILE__, __LINE__
20
+ end
21
+ end
22
+ end
@@ -1,12 +1,10 @@
1
- require 'active_support/concern'
2
-
3
1
  module ActiveRecord
4
2
  module Sanitization
5
3
  extend ActiveSupport::Concern
6
4
 
7
5
  module ClassMethods
8
- def quote_value(value, column = nil) #:nodoc:
9
- connection.quote(value,column)
6
+ def quote_value(value, column) #:nodoc:
7
+ connection.quote(value, column)
10
8
  end
11
9
 
12
10
  # Used to sanitize objects before they're used in an SQL SELECT statement. Delegates to <tt>connection.quote</tt>.
@@ -19,7 +17,7 @@ module ActiveRecord
19
17
  # Accepts an array, hash, or string of SQL conditions and sanitizes
20
18
  # them into a valid SQL fragment for a WHERE clause.
21
19
  # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'"
22
- # { :name => "foo'bar", :group_id => 4 } returns "name='foo''bar' and group_id='4'"
20
+ # { name: "foo'bar", group_id: 4 } returns "name='foo''bar' and group_id='4'"
23
21
  # "name='foo''bar' and group_id='4'" returns "name='foo''bar' and group_id='4'"
24
22
  def sanitize_sql_for_conditions(condition, table_name = self.table_name)
25
23
  return nil if condition.blank?
@@ -31,15 +29,16 @@ module ActiveRecord
31
29
  end
32
30
  end
33
31
  alias_method :sanitize_sql, :sanitize_sql_for_conditions
32
+ alias_method :sanitize_conditions, :sanitize_sql
34
33
 
35
34
  # Accepts an array, hash, or string of SQL conditions and sanitizes
36
35
  # them into a valid SQL fragment for a SET clause.
37
- # { :name => nil, :group_id => 4 } returns "name = NULL , group_id='4'"
38
- def sanitize_sql_for_assignment(assignments)
36
+ # { name: nil, group_id: 4 } returns "name = NULL , group_id='4'"
37
+ def sanitize_sql_for_assignment(assignments, default_table_name = self.table_name)
39
38
  case assignments
40
- when Array; sanitize_sql_array(assignments)
41
- when Hash; sanitize_sql_hash_for_assignment(assignments)
42
- else assignments
39
+ when Array; sanitize_sql_array(assignments)
40
+ when Hash; sanitize_sql_hash_for_assignment(assignments, default_table_name)
41
+ else assignments
43
42
  end
44
43
  end
45
44
 
@@ -48,17 +47,17 @@ module ActiveRecord
48
47
  # aggregate attribute values.
49
48
  # Given:
50
49
  # class Person < ActiveRecord::Base
51
- # composed_of :address, :class_name => "Address",
52
- # :mapping => [%w(address_street street), %w(address_city city)]
50
+ # composed_of :address, class_name: "Address",
51
+ # mapping: [%w(address_street street), %w(address_city city)]
53
52
  # end
54
53
  # Then:
55
- # { :address => Address.new("813 abc st.", "chicago") }
56
- # # => { :address_street => "813 abc st.", :address_city => "chicago" }
54
+ # { address: Address.new("813 abc st.", "chicago") }
55
+ # # => { address_street: "813 abc st.", address_city: "chicago" }
57
56
  def expand_hash_conditions_for_aggregates(attrs)
58
57
  expanded_attrs = {}
59
58
  attrs.each do |attr, value|
60
- unless (aggregation = reflect_on_aggregation(attr.to_sym)).nil?
61
- mapping = aggregate_mapping(aggregation)
59
+ if aggregation = reflect_on_aggregation(attr.to_sym)
60
+ mapping = aggregation.mapping
62
61
  mapping.each do |field_attr, aggregate_attr|
63
62
  if mapping.size == 1 && !value.respond_to?(aggregate_attr)
64
63
  expanded_attrs[field_attr] = value
@@ -74,38 +73,50 @@ module ActiveRecord
74
73
  end
75
74
 
76
75
  # Sanitizes a hash of attribute/value pairs into SQL conditions for a WHERE clause.
77
- # { :name => "foo'bar", :group_id => 4 }
76
+ # { name: "foo'bar", group_id: 4 }
78
77
  # # => "name='foo''bar' and group_id= 4"
79
- # { :status => nil, :group_id => [1,2,3] }
78
+ # { status: nil, group_id: [1,2,3] }
80
79
  # # => "status IS NULL and group_id IN (1,2,3)"
81
- # { :age => 13..18 }
80
+ # { age: 13..18 }
82
81
  # # => "age BETWEEN 13 AND 18"
83
82
  # { 'other_records.id' => 7 }
84
83
  # # => "`other_records`.`id` = 7"
85
- # { :other_records => { :id => 7 } }
84
+ # { other_records: { id: 7 } }
86
85
  # # => "`other_records`.`id` = 7"
87
86
  # And for value objects on a composed_of relationship:
88
- # { :address => Address.new("123 abc st.", "chicago") }
87
+ # { address: Address.new("123 abc st.", "chicago") }
89
88
  # # => "address_street='123 abc st.' and address_city='chicago'"
90
89
  def sanitize_sql_hash_for_conditions(attrs, default_table_name = self.table_name)
90
+ ActiveSupport::Deprecation.warn(<<-EOWARN)
91
+ sanitize_sql_hash_for_conditions is deprecated, and will be removed in Rails 5.0
92
+ EOWARN
93
+ attrs = PredicateBuilder.resolve_column_aliases self, attrs
91
94
  attrs = expand_hash_conditions_for_aggregates(attrs)
92
95
 
93
- table = Arel::Table.new(table_name).alias(default_table_name)
94
- PredicateBuilder.build_from_hash(arel_engine, attrs, table).map { |b|
95
- connection.visitor.accept b
96
+ table = Arel::Table.new(table_name, arel_engine).alias(default_table_name)
97
+ PredicateBuilder.build_from_hash(self, attrs, table).map { |b|
98
+ connection.visitor.compile b
96
99
  }.join(' AND ')
97
100
  end
98
101
  alias_method :sanitize_sql_hash, :sanitize_sql_hash_for_conditions
99
102
 
100
103
  # Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
101
- # { :status => nil, :group_id => 1 }
104
+ # { status: nil, group_id: 1 }
102
105
  # # => "status = NULL , group_id = 1"
103
- def sanitize_sql_hash_for_assignment(attrs)
106
+ def sanitize_sql_hash_for_assignment(attrs, table)
107
+ c = connection
104
108
  attrs.map do |attr, value|
105
- "#{connection.quote_column_name(attr)} = #{quote_bound_value(value)}"
109
+ "#{c.quote_table_name_for_assignment(table, attr)} = #{quote_bound_value(value, c, columns_hash[attr.to_s])}"
106
110
  end.join(', ')
107
111
  end
108
112
 
113
+ # Sanitizes a +string+ so that it is safe to use within an SQL
114
+ # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%"
115
+ def sanitize_sql_like(string, escape_character = "\\")
116
+ pattern = Regexp.union(escape_character, "%", "_")
117
+ string.gsub(pattern) { |x| [escape_character, x].join }
118
+ end
119
+
109
120
  # Accepts an array of conditions. The array has each value
110
121
  # sanitized and interpolated into the SQL statement.
111
122
  # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'"
@@ -122,13 +133,21 @@ module ActiveRecord
122
133
  end
123
134
  end
124
135
 
125
- alias_method :sanitize_conditions, :sanitize_sql
126
-
127
136
  def replace_bind_variables(statement, values) #:nodoc:
128
137
  raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
129
138
  bound = values.dup
130
139
  c = connection
131
- statement.gsub('?') { quote_bound_value(bound.shift, c) }
140
+ statement.gsub(/\?/) do
141
+ replace_bind_variable(bound.shift, c)
142
+ end
143
+ end
144
+
145
+ def replace_bind_variable(value, c = connection) #:nodoc:
146
+ if ActiveRecord::Relation === value
147
+ value.to_sql
148
+ else
149
+ quote_bound_value(value, c)
150
+ end
132
151
  end
133
152
 
134
153
  def replace_named_bind_variables(statement, bind_vars) #:nodoc:
@@ -136,32 +155,17 @@ module ActiveRecord
136
155
  if $1 == ':' # skip postgresql casts
137
156
  $& # return the whole match
138
157
  elsif bind_vars.include?(match = $2.to_sym)
139
- quote_bound_value(bind_vars[match])
158
+ replace_bind_variable(bind_vars[match])
140
159
  else
141
160
  raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
142
161
  end
143
162
  end
144
163
  end
145
164
 
146
- def expand_range_bind_variables(bind_vars) #:nodoc:
147
- expanded = []
148
-
149
- bind_vars.each do |var|
150
- next if var.is_a?(Hash)
151
-
152
- if var.is_a?(Range)
153
- expanded << var.first
154
- expanded << var.last
155
- else
156
- expanded << var
157
- end
158
- end
159
-
160
- expanded
161
- end
162
-
163
- def quote_bound_value(value, c = connection) #:nodoc:
164
- if value.respond_to?(:map) && !value.acts_like?(:string)
165
+ def quote_bound_value(value, c = connection, column = nil) #:nodoc:
166
+ if column
167
+ c.quote(value, column)
168
+ elsif value.respond_to?(:map) && !value.acts_like?(:string)
165
169
  if value.respond_to?(:empty?) && value.empty?
166
170
  c.quote(nil)
167
171
  else
@@ -180,15 +184,8 @@ module ActiveRecord
180
184
  end
181
185
 
182
186
  # TODO: Deprecate this
183
- def quoted_id #:nodoc:
184
- quote_value(id, column_for_attribute(self.class.primary_key))
185
- end
186
-
187
- private
188
-
189
- # Quote strings appropriately for SQL statements.
190
- def quote_value(value, column = nil)
191
- self.class.connection.quote(value, column)
187
+ def quoted_id
188
+ self.class.quote_value(id, column_for_attribute(self.class.primary_key))
192
189
  end
193
190
  end
194
191
  end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/object/blank'
2
-
3
1
  module ActiveRecord
4
2
  # = Active Record Schema
5
3
  #
@@ -12,16 +10,16 @@ module ActiveRecord
12
10
  #
13
11
  # ActiveRecord::Schema.define do
14
12
  # create_table :authors do |t|
15
- # t.string :name, :null => false
13
+ # t.string :name, null: false
16
14
  # end
17
15
  #
18
16
  # add_index :authors, :name, :unique
19
17
  #
20
18
  # create_table :posts do |t|
21
- # t.integer :author_id, :null => false
19
+ # t.integer :author_id, null: false
22
20
  # t.string :subject
23
21
  # t.text :body
24
- # t.boolean :private, :default => false
22
+ # t.boolean :private, default: false
25
23
  # end
26
24
  #
27
25
  # add_index :posts, :author_id
@@ -30,10 +28,24 @@ module ActiveRecord
30
28
  # ActiveRecord::Schema is only supported by database adapters that also
31
29
  # support migrations, the two features being very similar.
32
30
  class Schema < Migration
31
+
32
+ # Returns the migrations paths.
33
+ #
34
+ # ActiveRecord::Schema.new.migrations_paths
35
+ # # => ["db/migrate"] # Rails migration path by default.
33
36
  def migrations_paths
34
37
  ActiveRecord::Migrator.migrations_paths
35
38
  end
36
39
 
40
+ def define(info, &block) # :nodoc:
41
+ instance_eval(&block)
42
+
43
+ unless info[:version].blank?
44
+ initialize_schema_migrations_table
45
+ connection.assume_migrated_upto_version(info[:version], migrations_paths)
46
+ end
47
+ end
48
+
37
49
  # Eval the given block. All methods available to the current connection
38
50
  # adapter are available within the block, so you can easily use the
39
51
  # database definition DSL to build up your schema (+create_table+,
@@ -42,17 +54,11 @@ module ActiveRecord
42
54
  # The +info+ hash is optional, and if given is used to define metadata
43
55
  # about the current schema (currently, only the schema's version):
44
56
  #
45
- # ActiveRecord::Schema.define(:version => 20380119000001) do
57
+ # ActiveRecord::Schema.define(version: 20380119000001) do
46
58
  # ...
47
59
  # end
48
60
  def self.define(info={}, &block)
49
- schema = new
50
- schema.instance_eval(&block)
51
-
52
- unless info[:version].blank?
53
- initialize_schema_migrations_table
54
- assume_migrated_upto_version(info[:version], schema.migrations_paths)
55
- end
61
+ new.define(info, &block)
56
62
  end
57
63
  end
58
64
  end