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,40 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class StatementPool
4
+ include Enumerable
5
+
6
+ def initialize(connection, max = 1000)
7
+ @connection = connection
8
+ @max = max
9
+ end
10
+
11
+ def each
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def key?(key)
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def [](key)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def length
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def []=(sql, key)
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def clear
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def delete(key)
36
+ raise NotImplementedError
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,132 @@
1
+ module ActiveRecord
2
+ module ConnectionHandling
3
+ RAILS_ENV = -> { (Rails.env if defined?(Rails)) || ENV["RAILS_ENV"] || ENV["RACK_ENV"] }
4
+ DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
5
+
6
+ # Establishes the connection to the database. Accepts a hash as input where
7
+ # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
8
+ # example for regular databases (MySQL, Postgresql, etc):
9
+ #
10
+ # ActiveRecord::Base.establish_connection(
11
+ # adapter: "mysql",
12
+ # host: "localhost",
13
+ # username: "myuser",
14
+ # password: "mypass",
15
+ # database: "somedatabase"
16
+ # )
17
+ #
18
+ # Example for SQLite database:
19
+ #
20
+ # ActiveRecord::Base.establish_connection(
21
+ # adapter: "sqlite3",
22
+ # database: "path/to/dbfile"
23
+ # )
24
+ #
25
+ # Also accepts keys as strings (for parsing from YAML for example):
26
+ #
27
+ # ActiveRecord::Base.establish_connection(
28
+ # "adapter" => "sqlite3",
29
+ # "database" => "path/to/dbfile"
30
+ # )
31
+ #
32
+ # Or a URL:
33
+ #
34
+ # ActiveRecord::Base.establish_connection(
35
+ # "postgres://myuser:mypass@localhost/somedatabase"
36
+ # )
37
+ #
38
+ # In case <tt>ActiveRecord::Base.configurations</tt> is set (Rails
39
+ # automatically loads the contents of config/database.yml into it),
40
+ # a symbol can also be given as argument, representing a key in the
41
+ # configuration hash:
42
+ #
43
+ # ActiveRecord::Base.establish_connection(:production)
44
+ #
45
+ # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
46
+ # may be returned on an error.
47
+ def establish_connection(spec = nil)
48
+ spec ||= DEFAULT_ENV.call.to_sym
49
+ resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
50
+ spec = resolver.spec(spec)
51
+
52
+ unless respond_to?(spec.adapter_method)
53
+ raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
54
+ end
55
+
56
+ remove_connection
57
+ connection_handler.establish_connection self, spec
58
+ end
59
+
60
+ class MergeAndResolveDefaultUrlConfig # :nodoc:
61
+ def initialize(raw_configurations)
62
+ @raw_config = raw_configurations.dup
63
+ @env = DEFAULT_ENV.call.to_s
64
+ end
65
+
66
+ # Returns fully resolved connection hashes.
67
+ # Merges connection information from `ENV['DATABASE_URL']` if available.
68
+ def resolve
69
+ ConnectionAdapters::ConnectionSpecification::Resolver.new(config).resolve_all
70
+ end
71
+
72
+ private
73
+ def config
74
+ @raw_config.dup.tap do |cfg|
75
+ if url = ENV['DATABASE_URL']
76
+ cfg[@env] ||= {}
77
+ cfg[@env]["url"] ||= url
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ # Returns the connection currently associated with the class. This can
84
+ # also be used to "borrow" the connection to do database work unrelated
85
+ # to any of the specific Active Records.
86
+ def connection
87
+ retrieve_connection
88
+ end
89
+
90
+ def connection_id
91
+ ActiveRecord::RuntimeRegistry.connection_id
92
+ end
93
+
94
+ def connection_id=(connection_id)
95
+ ActiveRecord::RuntimeRegistry.connection_id = connection_id
96
+ end
97
+
98
+ # Returns the configuration of the associated connection as a hash:
99
+ #
100
+ # ActiveRecord::Base.connection_config
101
+ # # => {pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}
102
+ #
103
+ # Please use only for reading.
104
+ def connection_config
105
+ connection_pool.spec.config
106
+ end
107
+
108
+ def connection_pool
109
+ connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
110
+ end
111
+
112
+ def retrieve_connection
113
+ connection_handler.retrieve_connection(self)
114
+ end
115
+
116
+ # Returns +true+ if Active Record is connected.
117
+ def connected?
118
+ connection_handler.connected?(self)
119
+ end
120
+
121
+ def remove_connection(klass = self)
122
+ connection_handler.remove_connection(klass)
123
+ end
124
+
125
+ def clear_cache! # :nodoc:
126
+ connection.schema_cache.clear!
127
+ end
128
+
129
+ delegate :clear_active_connections!, :clear_reloadable_connections!,
130
+ :clear_all_connections!, :to => :connection_handler
131
+ end
132
+ end
@@ -0,0 +1,566 @@
1
+ require 'thread'
2
+ require 'active_support/core_ext/hash/indifferent_access'
3
+ require 'active_support/core_ext/object/duplicable'
4
+ require 'active_support/core_ext/string/filters'
5
+
6
+ module ActiveRecord
7
+ module Core
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ ##
12
+ # :singleton-method:
13
+ #
14
+ # Accepts a logger conforming to the interface of Log4r which is then
15
+ # passed on to any new database connections made and which can be
16
+ # retrieved on both a class and instance level by calling +logger+.
17
+ mattr_accessor :logger, instance_writer: false
18
+
19
+ ##
20
+ # Contains the database configuration - as is typically stored in config/database.yml -
21
+ # as a Hash.
22
+ #
23
+ # For example, the following database.yml...
24
+ #
25
+ # development:
26
+ # adapter: sqlite3
27
+ # database: db/development.sqlite3
28
+ #
29
+ # production:
30
+ # adapter: sqlite3
31
+ # database: db/production.sqlite3
32
+ #
33
+ # ...would result in ActiveRecord::Base.configurations to look like this:
34
+ #
35
+ # {
36
+ # 'development' => {
37
+ # 'adapter' => 'sqlite3',
38
+ # 'database' => 'db/development.sqlite3'
39
+ # },
40
+ # 'production' => {
41
+ # 'adapter' => 'sqlite3',
42
+ # 'database' => 'db/production.sqlite3'
43
+ # }
44
+ # }
45
+ def self.configurations=(config)
46
+ @@configurations = ActiveRecord::ConnectionHandling::MergeAndResolveDefaultUrlConfig.new(config).resolve
47
+ end
48
+ self.configurations = {}
49
+
50
+ # Returns fully resolved configurations hash
51
+ def self.configurations
52
+ @@configurations
53
+ end
54
+
55
+ ##
56
+ # :singleton-method:
57
+ # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
58
+ # dates and times from the database. This is set to :utc by default.
59
+ mattr_accessor :default_timezone, instance_writer: false
60
+ self.default_timezone = :utc
61
+
62
+ ##
63
+ # :singleton-method:
64
+ # Specifies the format to use when dumping the database schema with Rails'
65
+ # Rakefile. If :sql, the schema is dumped as (potentially database-
66
+ # specific) SQL statements. If :ruby, the schema is dumped as an
67
+ # ActiveRecord::Schema file which can be loaded into any database that
68
+ # supports migrations. Use :ruby if you want to have different database
69
+ # adapters for, e.g., your development and test environments.
70
+ mattr_accessor :schema_format, instance_writer: false
71
+ self.schema_format = :ruby
72
+
73
+ ##
74
+ # :singleton-method:
75
+ # Specify whether or not to use timestamps for migration versions
76
+ mattr_accessor :timestamped_migrations, instance_writer: false
77
+ self.timestamped_migrations = true
78
+
79
+ ##
80
+ # :singleton-method:
81
+ # Specify whether schema dump should happen at the end of the
82
+ # db:migrate rake task. This is true by default, which is useful for the
83
+ # development environment. This should ideally be false in the production
84
+ # environment where dumping schema is rarely needed.
85
+ mattr_accessor :dump_schema_after_migration, instance_writer: false
86
+ self.dump_schema_after_migration = true
87
+
88
+ mattr_accessor :maintain_test_schema, instance_accessor: false
89
+
90
+ def self.disable_implicit_join_references=(value)
91
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
92
+ Implicit join references were removed with Rails 4.1.
93
+ Make sure to remove this configuration because it does nothing.
94
+ MSG
95
+ end
96
+
97
+ class_attribute :default_connection_handler, instance_writer: false
98
+ class_attribute :find_by_statement_cache
99
+
100
+ def self.connection_handler
101
+ ActiveRecord::RuntimeRegistry.connection_handler || default_connection_handler
102
+ end
103
+
104
+ def self.connection_handler=(handler)
105
+ ActiveRecord::RuntimeRegistry.connection_handler = handler
106
+ end
107
+
108
+ self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
109
+ end
110
+
111
+ module ClassMethods
112
+ def allocate
113
+ define_attribute_methods
114
+ super
115
+ end
116
+
117
+ def initialize_find_by_cache
118
+ self.find_by_statement_cache = {}.extend(Mutex_m)
119
+ end
120
+
121
+ def inherited(child_class)
122
+ child_class.initialize_find_by_cache
123
+ super
124
+ end
125
+
126
+ def find(*ids)
127
+ # We don't have cache keys for this stuff yet
128
+ return super unless ids.length == 1
129
+ # Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
130
+ return super if ids.first.kind_of?(Symbol)
131
+ return super if block_given? ||
132
+ primary_key.nil? ||
133
+ default_scopes.any? ||
134
+ columns_hash.include?(inheritance_column) ||
135
+ ids.first.kind_of?(Array)
136
+
137
+ id = ids.first
138
+ if ActiveRecord::Base === id
139
+ id = id.id
140
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
141
+ You are passing an instance of ActiveRecord::Base to `find`.
142
+ Please pass the id of the object by calling `.id`
143
+ MSG
144
+ end
145
+ key = primary_key
146
+
147
+ s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
148
+ find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
149
+ where(key => params.bind).limit(1)
150
+ }
151
+ }
152
+ record = s.execute([id], self, connection).first
153
+ unless record
154
+ raise RecordNotFound, "Couldn't find #{name} with '#{primary_key}'=#{id}"
155
+ end
156
+ record
157
+ rescue RangeError
158
+ raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
159
+ end
160
+
161
+ def find_by(*args)
162
+ return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any?
163
+ return super if default_scopes.any?
164
+
165
+ hash = args.first
166
+
167
+ return super if hash.values.any? { |v|
168
+ v.nil? || Array === v || Hash === v
169
+ }
170
+
171
+ # We can't cache Post.find_by(author: david) ...yet
172
+ return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
173
+
174
+ key = hash.keys
175
+
176
+ klass = self
177
+ s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
178
+ find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
179
+ wheres = key.each_with_object({}) { |param,o|
180
+ o[param] = params.bind
181
+ }
182
+ klass.where(wheres).limit(1)
183
+ }
184
+ }
185
+ begin
186
+ s.execute(hash.values, self, connection).first
187
+ rescue TypeError => e
188
+ raise ActiveRecord::StatementInvalid.new(e.message, e)
189
+ rescue RangeError
190
+ nil
191
+ end
192
+ end
193
+
194
+ def find_by!(*args)
195
+ find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}")
196
+ end
197
+
198
+ def initialize_generated_modules
199
+ generated_association_methods
200
+ end
201
+
202
+ def generated_association_methods
203
+ @generated_association_methods ||= begin
204
+ mod = const_set(:GeneratedAssociationMethods, Module.new)
205
+ include mod
206
+ mod
207
+ end
208
+ end
209
+
210
+ # Returns a string like 'Post(id:integer, title:string, body:text)'
211
+ def inspect
212
+ if self == Base
213
+ super
214
+ elsif abstract_class?
215
+ "#{super}(abstract)"
216
+ elsif !connected?
217
+ "#{super} (call '#{super}.connection' to establish a connection)"
218
+ elsif table_exists?
219
+ attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
220
+ "#{super}(#{attr_list})"
221
+ else
222
+ "#{super}(Table doesn't exist)"
223
+ end
224
+ end
225
+
226
+ # Overwrite the default class equality method to provide support for association proxies.
227
+ def ===(object)
228
+ object.is_a?(self)
229
+ end
230
+
231
+ # Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
232
+ #
233
+ # class Post < ActiveRecord::Base
234
+ # scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
235
+ # end
236
+ def arel_table # :nodoc:
237
+ @arel_table ||= Arel::Table.new(table_name, arel_engine)
238
+ end
239
+
240
+ # Returns the Arel engine.
241
+ def arel_engine # :nodoc:
242
+ @arel_engine ||=
243
+ if Base == self || connection_handler.retrieve_connection_pool(self)
244
+ self
245
+ else
246
+ superclass.arel_engine
247
+ end
248
+ end
249
+
250
+ private
251
+
252
+ def relation #:nodoc:
253
+ relation = Relation.create(self, arel_table)
254
+
255
+ if finder_needs_type_condition?
256
+ relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
257
+ else
258
+ relation
259
+ end
260
+ end
261
+ end
262
+
263
+ # New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
264
+ # attributes but not yet saved (pass a hash with key names matching the associated table column names).
265
+ # In both instances, valid attribute keys are determined by the column names of the associated table --
266
+ # hence you can't have attributes that aren't part of the table columns.
267
+ #
268
+ # ==== Example:
269
+ # # Instantiates a single new object
270
+ # User.new(first_name: 'Jamie')
271
+ def initialize(attributes = nil, options = {})
272
+ @attributes = self.class._default_attributes.dup
273
+
274
+ init_internals
275
+ initialize_internals_callback
276
+
277
+ self.class.define_attribute_methods
278
+ # +options+ argument is only needed to make protected_attributes gem easier to hook.
279
+ # Remove it when we drop support to this gem.
280
+ init_attributes(attributes, options) if attributes
281
+
282
+ yield self if block_given?
283
+ _run_initialize_callbacks
284
+ end
285
+
286
+ # Initialize an empty model object from +coder+. +coder+ must contain
287
+ # the attributes necessary for initializing an empty model object. For
288
+ # example:
289
+ #
290
+ # class Post < ActiveRecord::Base
291
+ # end
292
+ #
293
+ # post = Post.allocate
294
+ # post.init_with('attributes' => { 'title' => 'hello world' })
295
+ # post.title # => 'hello world'
296
+ def init_with(coder)
297
+ @attributes = coder['attributes']
298
+
299
+ init_internals
300
+
301
+ @new_record = coder['new_record']
302
+
303
+ self.class.define_attribute_methods
304
+
305
+ _run_find_callbacks
306
+ _run_initialize_callbacks
307
+
308
+ self
309
+ end
310
+
311
+ ##
312
+ # :method: clone
313
+ # Identical to Ruby's clone method. This is a "shallow" copy. Be warned that your attributes are not copied.
314
+ # That means that modifying attributes of the clone will modify the original, since they will both point to the
315
+ # same attributes hash. If you need a copy of your attributes hash, please use the #dup method.
316
+ #
317
+ # user = User.first
318
+ # new_user = user.clone
319
+ # user.name # => "Bob"
320
+ # new_user.name = "Joe"
321
+ # user.name # => "Joe"
322
+ #
323
+ # user.object_id == new_user.object_id # => false
324
+ # user.name.object_id == new_user.name.object_id # => true
325
+ #
326
+ # user.name.object_id == user.dup.name.object_id # => false
327
+
328
+ ##
329
+ # :method: dup
330
+ # Duped objects have no id assigned and are treated as new records. Note
331
+ # that this is a "shallow" copy as it copies the object's attributes
332
+ # only, not its associations. The extent of a "deep" copy is application
333
+ # specific and is therefore left to the application to implement according
334
+ # to its need.
335
+ # The dup method does not preserve the timestamps (created|updated)_(at|on).
336
+
337
+ ##
338
+ def initialize_dup(other) # :nodoc:
339
+ @attributes = @attributes.dup
340
+ @attributes.reset(self.class.primary_key)
341
+
342
+ _run_initialize_callbacks
343
+
344
+ @aggregation_cache = {}
345
+ @association_cache = {}
346
+
347
+ @new_record = true
348
+ @destroyed = false
349
+
350
+ super
351
+ end
352
+
353
+ # Populate +coder+ with attributes about this record that should be
354
+ # serialized. The structure of +coder+ defined in this method is
355
+ # guaranteed to match the structure of +coder+ passed to the +init_with+
356
+ # method.
357
+ #
358
+ # Example:
359
+ #
360
+ # class Post < ActiveRecord::Base
361
+ # end
362
+ # coder = {}
363
+ # Post.new.encode_with(coder)
364
+ # coder # => {"attributes" => {"id" => nil, ... }}
365
+ def encode_with(coder)
366
+ # FIXME: Remove this when we better serialize attributes
367
+ coder['raw_attributes'] = attributes_before_type_cast
368
+ coder['attributes'] = @attributes
369
+ coder['new_record'] = new_record?
370
+ end
371
+
372
+ # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
373
+ # is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
374
+ #
375
+ # Note that new records are different from any other record by definition, unless the
376
+ # other record is the receiver itself. Besides, if you fetch existing records with
377
+ # +select+ and leave the ID out, you're on your own, this predicate will return false.
378
+ #
379
+ # Note also that destroying a record preserves its ID in the model instance, so deleted
380
+ # models are still comparable.
381
+ def ==(comparison_object)
382
+ super ||
383
+ comparison_object.instance_of?(self.class) &&
384
+ !id.nil? &&
385
+ comparison_object.id == id
386
+ end
387
+ alias :eql? :==
388
+
389
+ # Delegates to id in order to allow two records of the same type and id to work with something like:
390
+ # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
391
+ def hash
392
+ if id
393
+ id.hash
394
+ else
395
+ super
396
+ end
397
+ end
398
+
399
+ # Clone and freeze the attributes hash such that associations are still
400
+ # accessible, even on destroyed records, but cloned models will not be
401
+ # frozen.
402
+ def freeze
403
+ @attributes = @attributes.clone.freeze
404
+ self
405
+ end
406
+
407
+ # Returns +true+ if the attributes hash has been frozen.
408
+ def frozen?
409
+ @attributes.frozen?
410
+ end
411
+
412
+ # Allows sort on objects
413
+ def <=>(other_object)
414
+ if other_object.is_a?(self.class)
415
+ self.to_key <=> other_object.to_key
416
+ else
417
+ super
418
+ end
419
+ end
420
+
421
+ # Returns +true+ if the record is read only. Records loaded through joins with piggy-back
422
+ # attributes will be marked as read only since they cannot be saved.
423
+ def readonly?
424
+ @readonly
425
+ end
426
+
427
+ # Marks this record as read only.
428
+ def readonly!
429
+ @readonly = true
430
+ end
431
+
432
+ def connection_handler
433
+ self.class.connection_handler
434
+ end
435
+
436
+ # Returns the contents of the record as a nicely formatted string.
437
+ def inspect
438
+ # We check defined?(@attributes) not to issue warnings if the object is
439
+ # allocated but not initialized.
440
+ inspection = if defined?(@attributes) && @attributes
441
+ self.class.column_names.collect { |name|
442
+ if has_attribute?(name)
443
+ "#{name}: #{attribute_for_inspect(name)}"
444
+ end
445
+ }.compact.join(", ")
446
+ else
447
+ "not initialized"
448
+ end
449
+ "#<#{self.class} #{inspection}>"
450
+ end
451
+
452
+ # Takes a PP and prettily prints this record to it, allowing you to get a nice result from `pp record`
453
+ # when pp is required.
454
+ def pretty_print(pp)
455
+ pp.object_address_group(self) do
456
+ if defined?(@attributes) && @attributes
457
+ column_names = self.class.column_names.select { |name| has_attribute?(name) || new_record? }
458
+ pp.seplist(column_names, proc { pp.text ',' }) do |column_name|
459
+ column_value = read_attribute(column_name)
460
+ pp.breakable ' '
461
+ pp.group(1) do
462
+ pp.text column_name
463
+ pp.text ':'
464
+ pp.breakable
465
+ pp.pp column_value
466
+ end
467
+ end
468
+ else
469
+ pp.breakable ' '
470
+ pp.text 'not initialized'
471
+ end
472
+ end
473
+ end
474
+
475
+ # Returns a hash of the given methods with their names as keys and returned values as values.
476
+ def slice(*methods)
477
+ Hash[methods.map! { |method| [method, public_send(method)] }].with_indifferent_access
478
+ end
479
+
480
+ def set_transaction_state(state) # :nodoc:
481
+ @transaction_state = state
482
+ end
483
+
484
+ def has_transactional_callbacks? # :nodoc:
485
+ !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_create_callbacks.empty?
486
+ end
487
+
488
+ private
489
+
490
+ # Updates the attributes on this particular ActiveRecord object so that
491
+ # if it is associated with a transaction, then the state of the AR object
492
+ # will be updated to reflect the current state of the transaction
493
+ #
494
+ # The @transaction_state variable stores the states of the associated
495
+ # transaction. This relies on the fact that a transaction can only be in
496
+ # one rollback or commit (otherwise a list of states would be required)
497
+ # Each AR object inside of a transaction carries that transaction's
498
+ # TransactionState.
499
+ #
500
+ # This method checks to see if the ActiveRecord object's state reflects
501
+ # the TransactionState, and rolls back or commits the ActiveRecord object
502
+ # as appropriate.
503
+ #
504
+ # Since ActiveRecord objects can be inside multiple transactions, this
505
+ # method recursively goes through the parent of the TransactionState and
506
+ # checks if the ActiveRecord object reflects the state of the object.
507
+ def sync_with_transaction_state
508
+ update_attributes_from_transaction_state(@transaction_state, 0)
509
+ end
510
+
511
+ def update_attributes_from_transaction_state(transaction_state, depth)
512
+ if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
513
+ unless @reflects_state[depth]
514
+ restore_transaction_record_state if transaction_state.rolledback?
515
+ clear_transaction_record_state
516
+ @reflects_state[depth] = true
517
+ end
518
+
519
+ if transaction_state.parent && !@reflects_state[depth+1]
520
+ update_attributes_from_transaction_state(transaction_state.parent, depth+1)
521
+ end
522
+ end
523
+ end
524
+
525
+ # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
526
+ # of the array, and then rescues from the possible NoMethodError. If those elements are
527
+ # ActiveRecord::Base's, then this triggers the various method_missing's that we have,
528
+ # which significantly impacts upon performance.
529
+ #
530
+ # So we can avoid the method_missing hit by explicitly defining #to_ary as nil here.
531
+ #
532
+ # See also http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
533
+ def to_ary # :nodoc:
534
+ nil
535
+ end
536
+
537
+ def init_internals
538
+ @aggregation_cache = {}
539
+ @association_cache = {}
540
+ @readonly = false
541
+ @destroyed = false
542
+ @marked_for_destruction = false
543
+ @destroyed_by_association = nil
544
+ @new_record = true
545
+ @txn = nil
546
+ @_start_transaction_state = {}
547
+ @transaction_state = nil
548
+ @reflects_state = [false]
549
+ end
550
+
551
+ def initialize_internals_callback
552
+ end
553
+
554
+ # This method is needed to make protected_attributes gem easier to hook.
555
+ # Remove it when we drop support to this gem.
556
+ def init_attributes(attributes, options)
557
+ assign_attributes(attributes)
558
+ end
559
+
560
+ def thaw
561
+ if frozen?
562
+ @attributes = @attributes.dup
563
+ end
564
+ end
565
+ end
566
+ end