activerecord 4.1.15 → 4.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +634 -2176
- data/README.rdoc +15 -10
- data/lib/active_record/aggregations.rb +12 -8
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/association_scope.rb +53 -21
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -29
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -11
- data/lib/active_record/associations/builder/has_one.rb +2 -2
- data/lib/active_record/associations/builder/singular_association.rb +8 -1
- data/lib/active_record/associations/collection_association.rb +32 -44
- data/lib/active_record/associations/collection_proxy.rb +1 -10
- data/lib/active_record/associations/has_many_association.rb +60 -14
- data/lib/active_record/associations/has_many_through_association.rb +34 -23
- data/lib/active_record/associations/has_one_association.rb +0 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +18 -14
- data/lib/active_record/associations/join_dependency.rb +7 -9
- data/lib/active_record/associations/preloader/association.rb +9 -5
- data/lib/active_record/associations/preloader/through_association.rb +3 -3
- data/lib/active_record/associations/preloader.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +16 -1
- data/lib/active_record/associations/through_association.rb +6 -22
- data/lib/active_record/associations.rb +58 -33
- data/lib/active_record/attribute.rb +131 -0
- data/lib/active_record/attribute_assignment.rb +19 -11
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -2
- data/lib/active_record/attribute_methods/dirty.rb +85 -42
- data/lib/active_record/attribute_methods/primary_key.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +14 -57
- data/lib/active_record/attribute_methods/serialization.rb +12 -146
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +32 -40
- data/lib/active_record/attribute_methods/write.rb +8 -23
- data/lib/active_record/attribute_methods.rb +53 -90
- data/lib/active_record/attribute_set/builder.rb +32 -0
- data/lib/active_record/attribute_set.rb +77 -0
- data/lib/active_record/attributes.rb +122 -0
- data/lib/active_record/autosave_association.rb +11 -21
- data/lib/active_record/base.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +69 -45
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -42
- data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -60
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +37 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +102 -21
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +9 -33
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +178 -55
- data/lib/active_record/connection_adapters/abstract/transaction.rb +120 -115
- data/lib/active_record/connection_adapters/abstract_adapter.rb +143 -57
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +156 -107
- data/lib/active_record/connection_adapters/column.rb +13 -244
- data/lib/active_record/connection_adapters/connection_specification.rb +6 -20
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -15
- data/lib/active_record/connection_adapters/mysql_adapter.rb +55 -143
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +39 -20
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +96 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +85 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +42 -122
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +154 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +86 -34
- data/lib/active_record/connection_adapters/postgresql/utils.rb +66 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +188 -452
- data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +54 -47
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +119 -22
- data/lib/active_record/counter_cache.rb +60 -6
- data/lib/active_record/enum.rb +9 -10
- data/lib/active_record/errors.rb +27 -26
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixtures.rb +52 -45
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +33 -8
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/locking/optimistic.rb +34 -16
- data/lib/active_record/migration/command_recorder.rb +19 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +22 -32
- data/lib/active_record/model_schema.rb +39 -48
- data/lib/active_record/nested_attributes.rb +8 -18
- data/lib/active_record/persistence.rb +39 -22
- data/lib/active_record/query_cache.rb +3 -3
- data/lib/active_record/querying.rb +1 -8
- data/lib/active_record/railtie.rb +17 -10
- data/lib/active_record/railties/databases.rake +47 -42
- data/lib/active_record/readonly_attributes.rb +0 -1
- data/lib/active_record/reflection.rb +225 -92
- data/lib/active_record/relation/batches.rb +0 -2
- data/lib/active_record/relation/calculations.rb +28 -32
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +42 -20
- data/lib/active_record/relation/merger.rb +0 -1
- data/lib/active_record/relation/predicate_builder/array_handler.rb +16 -11
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +0 -4
- data/lib/active_record/relation/predicate_builder.rb +1 -22
- data/lib/active_record/relation/query_methods.rb +98 -62
- data/lib/active_record/relation/spawn_methods.rb +6 -7
- data/lib/active_record/relation.rb +35 -11
- data/lib/active_record/result.rb +16 -9
- data/lib/active_record/sanitization.rb +8 -1
- data/lib/active_record/schema.rb +0 -1
- data/lib/active_record/schema_dumper.rb +51 -9
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping/default.rb +5 -4
- data/lib/active_record/serializers/xml_serializer.rb +3 -7
- data/lib/active_record/statement_cache.rb +79 -5
- data/lib/active_record/store.rb +5 -5
- data/lib/active_record/tasks/database_tasks.rb +37 -5
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -2
- data/lib/active_record/timestamp.rb +9 -7
- data/lib/active_record/transactions.rb +35 -21
- data/lib/active_record/type/binary.rb +40 -0
- data/lib/active_record/type/boolean.rb +19 -0
- data/lib/active_record/type/date.rb +46 -0
- data/lib/active_record/type/date_time.rb +43 -0
- data/lib/active_record/type/decimal.rb +40 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +19 -0
- data/lib/active_record/type/integer.rb +23 -0
- data/lib/active_record/type/mutable.rb +16 -0
- data/lib/active_record/type/numeric.rb +36 -0
- data/lib/active_record/type/serialized.rb +51 -0
- data/lib/active_record/type/string.rb +36 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +26 -0
- data/lib/active_record/type/time_value.rb +38 -0
- data/lib/active_record/type/type_map.rb +48 -0
- data/lib/active_record/type/value.rb +101 -0
- data/lib/active_record/type.rb +20 -0
- data/lib/active_record/validations/uniqueness.rb +9 -23
- data/lib/active_record/validations.rb +21 -16
- data/lib/active_record.rb +2 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
- metadata +71 -14
- data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -195,7 +195,7 @@ module ActiveRecord
|
|
195
195
|
# == Database support
|
196
196
|
#
|
197
197
|
# Migrations are currently supported in MySQL, PostgreSQL, SQLite,
|
198
|
-
# SQL Server,
|
198
|
+
# SQL Server, and Oracle (all supported databases except DB2).
|
199
199
|
#
|
200
200
|
# == More examples
|
201
201
|
#
|
@@ -372,13 +372,21 @@ module ActiveRecord
|
|
372
372
|
end
|
373
373
|
|
374
374
|
def call(env)
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
375
|
+
if connection.supports_migrations?
|
376
|
+
mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
|
377
|
+
if @last_check < mtime
|
378
|
+
ActiveRecord::Migration.check_pending!(connection)
|
379
|
+
@last_check = mtime
|
380
|
+
end
|
379
381
|
end
|
380
382
|
@app.call(env)
|
381
383
|
end
|
384
|
+
|
385
|
+
private
|
386
|
+
|
387
|
+
def connection
|
388
|
+
ActiveRecord::Base.connection
|
389
|
+
end
|
382
390
|
end
|
383
391
|
|
384
392
|
class << self
|
@@ -391,14 +399,7 @@ module ActiveRecord
|
|
391
399
|
|
392
400
|
def load_schema_if_pending!
|
393
401
|
if ActiveRecord::Migrator.needs_migration?
|
394
|
-
|
395
|
-
FileUtils.cd Rails.root do
|
396
|
-
current_config = Base.connection_config
|
397
|
-
Base.clear_all_connections!
|
398
|
-
system("bin/rake db:test:prepare")
|
399
|
-
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
400
|
-
Base.establish_connection(current_config)
|
401
|
-
end
|
402
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema_current
|
402
403
|
check_pending!
|
403
404
|
end
|
404
405
|
end
|
@@ -649,7 +650,9 @@ module ActiveRecord
|
|
649
650
|
unless @connection.respond_to? :revert
|
650
651
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
651
652
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
652
|
-
|
653
|
+
if [:rename_table, :add_foreign_key].include?(method)
|
654
|
+
arguments[1] = proper_table_name(arguments.second, table_name_options)
|
655
|
+
end
|
653
656
|
end
|
654
657
|
end
|
655
658
|
return super unless connection.respond_to?(method)
|
@@ -811,22 +814,22 @@ module ActiveRecord
|
|
811
814
|
migrations = migrations(migrations_paths)
|
812
815
|
migrations.select! { |m| yield m } if block_given?
|
813
816
|
|
814
|
-
|
817
|
+
new(:up, migrations, target_version).migrate
|
815
818
|
end
|
816
819
|
|
817
820
|
def down(migrations_paths, target_version = nil, &block)
|
818
821
|
migrations = migrations(migrations_paths)
|
819
822
|
migrations.select! { |m| yield m } if block_given?
|
820
823
|
|
821
|
-
|
824
|
+
new(:down, migrations, target_version).migrate
|
822
825
|
end
|
823
826
|
|
824
827
|
def run(direction, migrations_paths, target_version)
|
825
|
-
|
828
|
+
new(direction, migrations(migrations_paths), target_version).run
|
826
829
|
end
|
827
830
|
|
828
831
|
def open(migrations_paths)
|
829
|
-
|
832
|
+
new(:up, migrations(migrations_paths), nil)
|
830
833
|
end
|
831
834
|
|
832
835
|
def schema_migrations_table_name
|
@@ -857,19 +860,6 @@ module ActiveRecord
|
|
857
860
|
migrations(migrations_paths).last || NullMigration.new
|
858
861
|
end
|
859
862
|
|
860
|
-
def proper_table_name(name, options = {})
|
861
|
-
ActiveSupport::Deprecation.warn "ActiveRecord::Migrator.proper_table_name is deprecated and will be removed in Rails 4.2. Use the proper_table_name instance method on ActiveRecord::Migration instead"
|
862
|
-
options = {
|
863
|
-
table_name_prefix: ActiveRecord::Base.table_name_prefix,
|
864
|
-
table_name_suffix: ActiveRecord::Base.table_name_suffix
|
865
|
-
}.merge(options)
|
866
|
-
if name.respond_to? :table_name
|
867
|
-
name.table_name
|
868
|
-
else
|
869
|
-
"#{options[:table_name_prefix]}#{name}#{options[:table_name_suffix]}"
|
870
|
-
end
|
871
|
-
end
|
872
|
-
|
873
863
|
def migrations_paths
|
874
864
|
@migrations_paths ||= ['db/migrate']
|
875
865
|
# just to not break things if someone uses: migration_path = some_string
|
@@ -901,7 +891,7 @@ module ActiveRecord
|
|
901
891
|
private
|
902
892
|
|
903
893
|
def move(direction, migrations_paths, steps)
|
904
|
-
migrator =
|
894
|
+
migrator = new(direction, migrations(migrations_paths))
|
905
895
|
start_index = migrator.migrations.index(migrator.current_migration)
|
906
896
|
|
907
897
|
if start_index
|
@@ -29,6 +29,10 @@ module ActiveRecord
|
|
29
29
|
# :singleton-method:
|
30
30
|
# Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
|
31
31
|
# "people_basecamp"). By default, the suffix is the empty string.
|
32
|
+
#
|
33
|
+
# If you are organising your models within modules, you can add a suffix to the models within
|
34
|
+
# a namespace by defining a singleton method in the parent module called table_name_suffix which
|
35
|
+
# returns your chosen suffix.
|
32
36
|
class_attribute :table_name_suffix, instance_writer: false
|
33
37
|
self.table_name_suffix = ""
|
34
38
|
|
@@ -47,6 +51,19 @@ module ActiveRecord
|
|
47
51
|
self.pluralize_table_names = true
|
48
52
|
|
49
53
|
self.inheritance_column = 'type'
|
54
|
+
|
55
|
+
delegate :type_for_attribute, to: :class
|
56
|
+
end
|
57
|
+
|
58
|
+
# Derives the join table name for +first_table+ and +second_table+. The
|
59
|
+
# table names appear in alphabetical order. A common prefix is removed
|
60
|
+
# (useful for namespaced models like Music::Artist and Music::Record):
|
61
|
+
#
|
62
|
+
# artists, records => artists_records
|
63
|
+
# records, artists => artists_records
|
64
|
+
# music_artists, music_records => music_artists_records
|
65
|
+
def self.derive_join_table_name(first_table, second_table) # :nodoc:
|
66
|
+
[first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').gsub("\0", "_")
|
50
67
|
end
|
51
68
|
|
52
69
|
module ClassMethods
|
@@ -153,6 +170,10 @@ module ActiveRecord
|
|
153
170
|
(parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
|
154
171
|
end
|
155
172
|
|
173
|
+
def full_table_name_suffix #:nodoc:
|
174
|
+
(parents.detect {|p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
|
175
|
+
end
|
176
|
+
|
156
177
|
# Defines the name of the table column which will store the class name on single-table
|
157
178
|
# inheritance situations.
|
158
179
|
#
|
@@ -190,7 +211,7 @@ module ActiveRecord
|
|
190
211
|
# given block. This is required for Oracle and is useful for any
|
191
212
|
# database which relies on sequences for primary key generation.
|
192
213
|
#
|
193
|
-
# If a sequence name is not explicitly set when using Oracle
|
214
|
+
# If a sequence name is not explicitly set when using Oracle,
|
194
215
|
# it will default to the commonly used pattern of: #{table_name}_seq
|
195
216
|
#
|
196
217
|
# If a sequence name is not explicitly set when using PostgreSQL, it
|
@@ -209,50 +230,29 @@ module ActiveRecord
|
|
209
230
|
connection.schema_cache.table_exists?(table_name)
|
210
231
|
end
|
211
232
|
|
212
|
-
|
213
|
-
|
214
|
-
@columns ||= connection.schema_cache.columns(table_name).map do |col|
|
215
|
-
col = col.dup
|
216
|
-
col.primary = (col.name == primary_key)
|
217
|
-
col
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
# Returns a hash of column objects for the table associated with this class.
|
222
|
-
def columns_hash
|
223
|
-
@columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
|
233
|
+
def attributes_builder # :nodoc:
|
234
|
+
@attributes_builder ||= AttributeSet::Builder.new(column_types)
|
224
235
|
end
|
225
236
|
|
226
237
|
def column_types # :nodoc:
|
227
|
-
@column_types ||=
|
228
|
-
|
229
|
-
|
230
|
-
def decorate_columns(columns_hash) # :nodoc:
|
231
|
-
return if columns_hash.empty?
|
232
|
-
|
233
|
-
@serialized_column_names ||= self.columns_hash.keys.find_all do |name|
|
234
|
-
serialized_attributes.key?(name)
|
235
|
-
end
|
236
|
-
|
237
|
-
@serialized_column_names.each do |name|
|
238
|
-
columns_hash[name] = AttributeMethods::Serialization::Type.new(columns_hash[name])
|
239
|
-
end
|
240
|
-
|
241
|
-
@time_zone_column_names ||= self.columns_hash.find_all do |name, col|
|
242
|
-
create_time_zone_conversion_attribute?(name, col)
|
243
|
-
end.map!(&:first)
|
244
|
-
|
245
|
-
@time_zone_column_names.each do |name|
|
246
|
-
columns_hash[name] = AttributeMethods::TimeZoneConversion::Type.new(columns_hash[name])
|
238
|
+
@column_types ||= columns_hash.transform_values(&:cast_type).tap do |h|
|
239
|
+
h.default = Type::Value.new
|
247
240
|
end
|
241
|
+
end
|
248
242
|
|
249
|
-
|
243
|
+
def type_for_attribute(attr_name) # :nodoc:
|
244
|
+
column_types[attr_name]
|
250
245
|
end
|
251
246
|
|
252
247
|
# Returns a hash where the keys are column names and the values are
|
253
248
|
# default values when instantiating the AR object for this table.
|
254
249
|
def column_defaults
|
255
|
-
|
250
|
+
default_attributes.to_hash
|
251
|
+
end
|
252
|
+
|
253
|
+
def default_attributes # :nodoc:
|
254
|
+
@default_attributes ||= attributes_builder.build_from_database(
|
255
|
+
columns_hash.transform_values(&:default))
|
256
256
|
end
|
257
257
|
|
258
258
|
# Returns an array of column names as strings.
|
@@ -263,7 +263,7 @@ module ActiveRecord
|
|
263
263
|
# Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
|
264
264
|
# and columns used for single table inheritance have been removed.
|
265
265
|
def content_columns
|
266
|
-
@content_columns ||= columns.reject { |c| c.
|
266
|
+
@content_columns ||= columns.reject { |c| c.name == primary_key || c.name =~ /(_id|_count)$/ || c.name == inheritance_column }
|
267
267
|
end
|
268
268
|
|
269
269
|
# Resets all the cached information about columns, which will cause them
|
@@ -298,27 +298,17 @@ module ActiveRecord
|
|
298
298
|
connection.schema_cache.clear_table_cache!(table_name) if table_exists?
|
299
299
|
|
300
300
|
@arel_engine = nil
|
301
|
-
@column_defaults = nil
|
302
301
|
@column_names = nil
|
303
|
-
@columns = nil
|
304
|
-
@columns_hash = nil
|
305
302
|
@column_types = nil
|
306
303
|
@content_columns = nil
|
304
|
+
@default_attributes = nil
|
307
305
|
@dynamic_methods_hash = nil
|
308
306
|
@inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
|
309
307
|
@relation = nil
|
310
|
-
@serialized_column_names = nil
|
311
308
|
@time_zone_column_names = nil
|
312
309
|
@cached_time_zone = nil
|
313
310
|
end
|
314
311
|
|
315
|
-
# This is a hook for use by modules that need to do extra stuff to
|
316
|
-
# attributes when they are initialized. (e.g. attribute
|
317
|
-
# serialization)
|
318
|
-
def initialize_attributes(attributes, options = {}) #:nodoc:
|
319
|
-
attributes
|
320
|
-
end
|
321
|
-
|
322
312
|
private
|
323
313
|
|
324
314
|
# Guesses the table name, but does not decorate it with prefix and suffix information.
|
@@ -337,7 +327,8 @@ module ActiveRecord
|
|
337
327
|
contained = contained.singularize if parent.pluralize_table_names
|
338
328
|
contained += '_'
|
339
329
|
end
|
340
|
-
|
330
|
+
|
331
|
+
"#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
|
341
332
|
else
|
342
333
|
# STI subclasses always use their superclass' table.
|
343
334
|
base.table_name
|
@@ -307,7 +307,7 @@ module ActiveRecord
|
|
307
307
|
attr_names.each do |association_name|
|
308
308
|
if reflection = _reflect_on_association(association_name)
|
309
309
|
reflection.autosave = true
|
310
|
-
|
310
|
+
add_autosave_association_callbacks(reflection)
|
311
311
|
|
312
312
|
nested_attributes_options = self.nested_attributes_options.dup
|
313
313
|
nested_attributes_options[association_name.to_sym] = options
|
@@ -485,10 +485,10 @@ module ActiveRecord
|
|
485
485
|
end
|
486
486
|
|
487
487
|
# Takes in a limit and checks if the attributes_collection has too many
|
488
|
-
# records.
|
489
|
-
# number-like
|
488
|
+
# records. It accepts limit in the form of symbol, proc, or
|
489
|
+
# number-like object (anything that can be compared with an integer).
|
490
490
|
#
|
491
|
-
#
|
491
|
+
# Raises TooManyRecords error if the attributes_collection is
|
492
492
|
# larger than the limit.
|
493
493
|
def check_record_limit!(limit, attributes_collection)
|
494
494
|
if limit
|
@@ -516,14 +516,14 @@ module ActiveRecord
|
|
516
516
|
|
517
517
|
# Determines if a hash contains a truthy _destroy key.
|
518
518
|
def has_destroy_flag?(hash)
|
519
|
-
|
519
|
+
Type::Boolean.new.type_cast_from_user(hash['_destroy'])
|
520
520
|
end
|
521
521
|
|
522
|
-
# Determines if a new record should be
|
522
|
+
# Determines if a new record should be rejected by checking
|
523
523
|
# has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
|
524
524
|
# association and evaluates to +true+.
|
525
525
|
def reject_new_record?(association_name, attributes)
|
526
|
-
|
526
|
+
has_destroy_flag?(attributes) || call_reject_if(association_name, attributes)
|
527
527
|
end
|
528
528
|
|
529
529
|
# Determines if a record with the particular +attributes+ should be
|
@@ -532,8 +532,7 @@ module ActiveRecord
|
|
532
532
|
#
|
533
533
|
# Returns false if there is a +destroy_flag+ on the attributes.
|
534
534
|
def call_reject_if(association_name, attributes)
|
535
|
-
return false if
|
536
|
-
|
535
|
+
return false if has_destroy_flag?(attributes)
|
537
536
|
case callback = self.nested_attributes_options[association_name][:reject_if]
|
538
537
|
when Symbol
|
539
538
|
method(callback).arity == 0 ? send(callback) : send(callback, attributes)
|
@@ -542,15 +541,6 @@ module ActiveRecord
|
|
542
541
|
end
|
543
542
|
end
|
544
543
|
|
545
|
-
# Only take into account the destroy flag if <tt>:allow_destroy</tt> is true
|
546
|
-
def will_be_destroyed?(association_name, attributes)
|
547
|
-
allow_destroy?(association_name) && has_destroy_flag?(attributes)
|
548
|
-
end
|
549
|
-
|
550
|
-
def allow_destroy?(association_name)
|
551
|
-
self.nested_attributes_options[association_name][:allow_destroy]
|
552
|
-
end
|
553
|
-
|
554
544
|
def raise_nested_attributes_record_not_found!(association_name, record_id)
|
555
545
|
raise RecordNotFound, "Couldn't find #{self.class._reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
|
556
546
|
end
|
@@ -36,6 +36,23 @@ module ActiveRecord
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
# Creates an object (or multiple objects) and saves it to the database,
|
40
|
+
# if validations pass. Raises a RecordInvalid error if validations fail,
|
41
|
+
# unlike Base#create.
|
42
|
+
#
|
43
|
+
# The +attributes+ parameter can be either a Hash or an Array of Hashes.
|
44
|
+
# These describe which attributes to be created on the object, or
|
45
|
+
# multiple objects when given an Array of Hashes.
|
46
|
+
def create!(attributes = nil, &block)
|
47
|
+
if attributes.is_a?(Array)
|
48
|
+
attributes.collect { |attr| create!(attr, &block) }
|
49
|
+
else
|
50
|
+
object = new(attributes, &block)
|
51
|
+
object.save!
|
52
|
+
object
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
39
56
|
# Given an attributes hash, +instantiate+ returns a new instance of
|
40
57
|
# the appropriate class. Accepts only keys as strings.
|
41
58
|
#
|
@@ -48,8 +65,8 @@ module ActiveRecord
|
|
48
65
|
# how this "single-table" inheritance mapping is implemented.
|
49
66
|
def instantiate(attributes, column_types = {})
|
50
67
|
klass = discriminate_class_for_record(attributes)
|
51
|
-
|
52
|
-
klass.allocate.init_with('attributes' => attributes, '
|
68
|
+
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
|
69
|
+
klass.allocate.init_with('attributes' => attributes, 'new_record' => false)
|
53
70
|
end
|
54
71
|
|
55
72
|
private
|
@@ -180,9 +197,7 @@ module ActiveRecord
|
|
180
197
|
def becomes(klass)
|
181
198
|
became = klass.new
|
182
199
|
became.instance_variable_set("@attributes", @attributes)
|
183
|
-
became.instance_variable_set("@
|
184
|
-
changed_attributes = @changed_attributes if defined?(@changed_attributes)
|
185
|
-
became.instance_variable_set("@changed_attributes", changed_attributes || {})
|
200
|
+
became.instance_variable_set("@changed_attributes", @changed_attributes) if defined?(@changed_attributes)
|
186
201
|
became.instance_variable_set("@new_record", new_record?)
|
187
202
|
became.instance_variable_set("@destroyed", destroyed?)
|
188
203
|
became.instance_variable_set("@errors", errors)
|
@@ -215,6 +230,8 @@ module ActiveRecord
|
|
215
230
|
#
|
216
231
|
# This method raises an +ActiveRecord::ActiveRecordError+ if the
|
217
232
|
# attribute is marked as readonly.
|
233
|
+
#
|
234
|
+
# See also +update_column+.
|
218
235
|
def update_attribute(name, value)
|
219
236
|
name = name.to_s
|
220
237
|
verify_readonly_attribute(name)
|
@@ -270,7 +287,8 @@ module ActiveRecord
|
|
270
287
|
# This method raises an +ActiveRecord::ActiveRecordError+ when called on new
|
271
288
|
# objects, or when at least one of the attributes is marked as readonly.
|
272
289
|
def update_columns(attributes)
|
273
|
-
raise ActiveRecordError, "cannot update
|
290
|
+
raise ActiveRecordError, "cannot update a new record" if new_record?
|
291
|
+
raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
|
274
292
|
|
275
293
|
attributes.each_key do |key|
|
276
294
|
verify_readonly_attribute(key.to_s)
|
@@ -395,25 +413,24 @@ module ActiveRecord
|
|
395
413
|
self.class.unscoped { self.class.find(id) }
|
396
414
|
end
|
397
415
|
|
398
|
-
@attributes
|
399
|
-
|
400
|
-
@column_types = self.class.column_types
|
401
|
-
@column_types_override = fresh_object.instance_variable_get('@column_types_override')
|
402
|
-
@attributes_cache = {}
|
403
|
-
@new_record = false
|
416
|
+
@attributes = fresh_object.instance_variable_get('@attributes')
|
417
|
+
@new_record = false
|
404
418
|
self
|
405
419
|
end
|
406
420
|
|
407
421
|
# Saves the record with the updated_at/on attributes set to the current time.
|
408
422
|
# Please note that no validation is performed and only the +after_touch+,
|
409
423
|
# +after_commit+ and +after_rollback+ callbacks are executed.
|
410
|
-
# If an attribute name is passed, that attribute is updated along with
|
411
|
-
# updated_at/on attributes.
|
412
424
|
#
|
413
|
-
#
|
414
|
-
#
|
425
|
+
# If attribute names are passed, they are updated along with updated_at/on
|
426
|
+
# attributes.
|
427
|
+
#
|
428
|
+
# product.touch # updates updated_at/on
|
429
|
+
# product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
|
430
|
+
# product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
|
415
431
|
#
|
416
|
-
# If used along with +belongs_to+ then +touch+ will invoke +touch+ method on
|
432
|
+
# If used along with +belongs_to+ then +touch+ will invoke +touch+ method on
|
433
|
+
# associated object.
|
417
434
|
#
|
418
435
|
# class Brake < ActiveRecord::Base
|
419
436
|
# belongs_to :car, touch: true
|
@@ -432,11 +449,11 @@ module ActiveRecord
|
|
432
449
|
# ball = Ball.new
|
433
450
|
# ball.touch(:updated_at) # => raises ActiveRecordError
|
434
451
|
#
|
435
|
-
def touch(
|
452
|
+
def touch(*names)
|
436
453
|
raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
|
437
454
|
|
438
455
|
attributes = timestamp_attributes_for_update_in_model
|
439
|
-
attributes
|
456
|
+
attributes.concat(names)
|
440
457
|
|
441
458
|
unless attributes.empty?
|
442
459
|
current_time = current_time_from_proper_timezone
|
@@ -449,7 +466,7 @@ module ActiveRecord
|
|
449
466
|
|
450
467
|
changes[self.class.locking_column] = increment_lock if locking_enabled?
|
451
468
|
|
452
|
-
|
469
|
+
clear_attribute_changes(changes.keys)
|
453
470
|
primary_key = self.class.primary_key
|
454
471
|
self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
|
455
472
|
else
|
@@ -487,7 +504,7 @@ module ActiveRecord
|
|
487
504
|
|
488
505
|
# Updates the associated record with values matching those of the instance attributes.
|
489
506
|
# Returns the number of affected rows.
|
490
|
-
def _update_record(attribute_names =
|
507
|
+
def _update_record(attribute_names = self.attribute_names)
|
491
508
|
attributes_values = arel_attributes_with_values_for_update(attribute_names)
|
492
509
|
if attributes_values.empty?
|
493
510
|
0
|
@@ -498,7 +515,7 @@ module ActiveRecord
|
|
498
515
|
|
499
516
|
# Creates a record with values matching those of the instance attributes
|
500
517
|
# and returns its id.
|
501
|
-
def _create_record(attribute_names =
|
518
|
+
def _create_record(attribute_names = self.attribute_names)
|
502
519
|
attributes_values = arel_attributes_with_values_for_create(attribute_names)
|
503
520
|
|
504
521
|
new_id = self.class.unscoped.insert attributes_values
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module ActiveRecord
|
3
2
|
# = Active Record Query Cache
|
4
3
|
class QueryCache
|
@@ -29,9 +28,10 @@ module ActiveRecord
|
|
29
28
|
end
|
30
29
|
|
31
30
|
def call(env)
|
32
|
-
|
31
|
+
connection = ActiveRecord::Base.connection
|
32
|
+
enabled = connection.query_cache_enabled
|
33
33
|
connection_id = ActiveRecord::Base.connection_id
|
34
|
-
|
34
|
+
connection.enable_query_cache!
|
35
35
|
|
36
36
|
response = @app.call(env)
|
37
37
|
response[2] = Rack::BodyProxy.new(response[2]) do
|
@@ -37,14 +37,7 @@ module ActiveRecord
|
|
37
37
|
# Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
|
38
38
|
def find_by_sql(sql, binds = [])
|
39
39
|
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds)
|
40
|
-
column_types =
|
41
|
-
|
42
|
-
if result_set.respond_to? :column_types
|
43
|
-
column_types = result_set.column_types
|
44
|
-
else
|
45
|
-
ActiveSupport::Deprecation.warn "the object returned from `select_all` must respond to `column_types`"
|
46
|
-
end
|
47
|
-
|
40
|
+
column_types = result_set.column_types.except(*columns_hash.keys)
|
48
41
|
result_set.map { |record| instantiate(record, column_types) }
|
49
42
|
end
|
50
43
|
|
@@ -36,6 +36,8 @@ module ActiveRecord
|
|
36
36
|
config.eager_load_namespaces << ActiveRecord
|
37
37
|
|
38
38
|
rake_tasks do
|
39
|
+
require "active_record/base"
|
40
|
+
|
39
41
|
namespace :db do
|
40
42
|
task :load_config do
|
41
43
|
ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration
|
@@ -114,17 +116,22 @@ module ActiveRecord
|
|
114
116
|
# and then establishes the connection.
|
115
117
|
initializer "active_record.initialize_database" do |app|
|
116
118
|
ActiveSupport.on_load(:active_record) do
|
119
|
+
self.configurations = Rails.application.config.database_configuration
|
117
120
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
end
|
124
|
-
end
|
121
|
+
begin
|
122
|
+
establish_connection
|
123
|
+
rescue ActiveRecord::NoDatabaseError
|
124
|
+
warn <<-end_warning
|
125
|
+
Oops - You have a database configured, but it doesn't exist yet!
|
125
126
|
|
126
|
-
|
127
|
-
|
127
|
+
Here's how to get started:
|
128
|
+
|
129
|
+
1. Configure your database in config/database.yml.
|
130
|
+
2. Run `bin/rake db:create` to create the database.
|
131
|
+
3. Run `bin/rake db:setup` to load your database schema.
|
132
|
+
end_warning
|
133
|
+
raise
|
134
|
+
end
|
128
135
|
end
|
129
136
|
end
|
130
137
|
|
@@ -142,8 +149,8 @@ module ActiveRecord
|
|
142
149
|
ActiveSupport.on_load(:active_record) do
|
143
150
|
ActionDispatch::Reloader.send(hook) do
|
144
151
|
if ActiveRecord::Base.connected?
|
145
|
-
ActiveRecord::Base.clear_cache!
|
146
152
|
ActiveRecord::Base.clear_reloadable_connections!
|
153
|
+
ActiveRecord::Base.clear_cache!
|
147
154
|
end
|
148
155
|
end
|
149
156
|
end
|