activerecord 4.2.0 → 5.2.8.1
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 +5 -5
- data/CHANGELOG.md +640 -928
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -11
- data/examples/performance.rb +32 -31
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +264 -247
- data/lib/active_record/association_relation.rb +24 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +87 -41
- data/lib/active_record/associations/association_scope.rb +106 -132
- data/lib/active_record/associations/belongs_to_association.rb +55 -36
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +29 -38
- data/lib/active_record/associations/builder/belongs_to.rb +77 -30
- data/lib/active_record/associations/builder/collection_association.rb +14 -23
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -39
- data/lib/active_record/associations/builder/has_many.rb +6 -4
- data/lib/active_record/associations/builder/has_one.rb +13 -6
- data/lib/active_record/associations/builder/singular_association.rb +15 -11
- data/lib/active_record/associations/collection_association.rb +145 -266
- data/lib/active_record/associations/collection_proxy.rb +242 -138
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +35 -75
- data/lib/active_record/associations/has_many_through_association.rb +51 -69
- data/lib/active_record/associations/has_one_association.rb +39 -24
- data/lib/active_record/associations/has_one_through_association.rb +18 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +40 -81
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +134 -154
- data/lib/active_record/associations/preloader/association.rb +85 -116
- data/lib/active_record/associations/preloader/through_association.rb +85 -74
- data/lib/active_record/associations/preloader.rb +83 -93
- data/lib/active_record/associations/singular_association.rb +27 -40
- data/lib/active_record/associations/through_association.rb +48 -23
- data/lib/active_record/associations.rb +1732 -1596
- data/lib/active_record/attribute_assignment.rb +58 -182
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -5
- data/lib/active_record/attribute_methods/dirty.rb +94 -125
- data/lib/active_record/attribute_methods/primary_key.rb +86 -71
- data/lib/active_record/attribute_methods/query.rb +4 -2
- data/lib/active_record/attribute_methods/read.rb +45 -63
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +62 -36
- data/lib/active_record/attribute_methods/write.rb +31 -46
- data/lib/active_record/attribute_methods.rb +170 -117
- data/lib/active_record/attributes.rb +201 -74
- data/lib/active_record/autosave_association.rb +118 -45
- data/lib/active_record/base.rb +60 -48
- data/lib/active_record/callbacks.rb +97 -57
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +37 -13
- data/lib/active_record/collection_cache_key.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +254 -87
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +72 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -52
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -217
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +617 -212
- data/lib/active_record/connection_adapters/abstract/transaction.rb +139 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +332 -191
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +567 -563
- data/lib/active_record/connection_adapters/column.rb +50 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +42 -195
- data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -115
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +65 -51
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +466 -280
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +439 -330
- data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -324
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +40 -27
- data/lib/active_record/core.rb +205 -202
- data/lib/active_record/counter_cache.rb +80 -37
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +136 -90
- data/lib/active_record/errors.rb +180 -52
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixtures.rb +193 -135
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +148 -112
- data/lib/active_record/integration.rb +70 -28
- data/lib/active_record/internal_metadata.rb +45 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +92 -98
- data/lib/active_record/locking/pessimistic.rb +15 -3
- data/lib/active_record/log_subscriber.rb +95 -33
- data/lib/active_record/migration/command_recorder.rb +133 -90
- data/lib/active_record/migration/compatibility.rb +217 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +594 -267
- data/lib/active_record/model_schema.rb +292 -111
- data/lib/active_record/nested_attributes.rb +266 -214
- data/lib/active_record/no_touching.rb +8 -2
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +350 -119
- data/lib/active_record/query_cache.rb +13 -24
- data/lib/active_record/querying.rb +19 -17
- data/lib/active_record/railtie.rb +117 -35
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +9 -3
- data/lib/active_record/railties/databases.rake +160 -174
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +447 -288
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +204 -55
- data/lib/active_record/relation/calculations.rb +259 -244
- data/lib/active_record/relation/delegation.rb +67 -60
- data/lib/active_record/relation/finder_methods.rb +290 -253
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +91 -68
- data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -23
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +118 -92
- data/lib/active_record/relation/query_attribute.rb +45 -0
- data/lib/active_record/relation/query_methods.rb +446 -389
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -16
- data/lib/active_record/relation/where_clause.rb +186 -0
- data/lib/active_record/relation/where_clause_factory.rb +34 -0
- data/lib/active_record/relation.rb +287 -339
- data/lib/active_record/result.rb +54 -36
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +155 -124
- data/lib/active_record/schema.rb +30 -24
- data/lib/active_record/schema_dumper.rb +91 -87
- data/lib/active_record/schema_migration.rb +19 -19
- data/lib/active_record/scoping/default.rb +102 -84
- data/lib/active_record/scoping/named.rb +81 -32
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +45 -35
- data/lib/active_record/store.rb +42 -36
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +82 -0
- data/lib/active_record/tasks/database_tasks.rb +136 -95
- data/lib/active_record/tasks/mysql_database_tasks.rb +59 -89
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -31
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +64 -0
- data/lib/active_record/transactions.rb +208 -123
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +136 -0
- data/lib/active_record/type/date.rb +4 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +30 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type.rb +79 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +41 -32
- data/lib/active_record/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -21
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -6
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -7
- data/lib/rails/generators/active_record/migration.rb +18 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +77 -53
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -149
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,83 +1,68 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module AttributeMethods
|
5
5
|
module Write
|
6
|
-
WriterMethodCache = Class.new(AttributeMethodCache) {
|
7
|
-
private
|
8
|
-
|
9
|
-
def method_body(method_name, const_name)
|
10
|
-
<<-EOMETHOD
|
11
|
-
def #{method_name}(value)
|
12
|
-
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{const_name}
|
13
|
-
write_attribute(name, value)
|
14
|
-
end
|
15
|
-
EOMETHOD
|
16
|
-
end
|
17
|
-
}.new
|
18
|
-
|
19
6
|
extend ActiveSupport::Concern
|
20
7
|
|
21
8
|
included do
|
22
9
|
attribute_method_suffix "="
|
23
10
|
end
|
24
11
|
|
25
|
-
module ClassMethods
|
26
|
-
|
12
|
+
module ClassMethods # :nodoc:
|
13
|
+
private
|
27
14
|
|
28
|
-
if Module.methods_transplantable?
|
29
15
|
def define_method_attribute=(name)
|
30
|
-
|
31
|
-
generated_attribute_methods.module_eval {
|
32
|
-
define_method "#{name}=", method
|
33
|
-
}
|
34
|
-
end
|
35
|
-
else
|
36
|
-
def define_method_attribute=(name)
|
37
|
-
safe_name = name.unpack('h*').first
|
16
|
+
safe_name = name.unpack("h*".freeze).first
|
38
17
|
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
18
|
+
sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
|
39
19
|
|
40
20
|
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
41
21
|
def __temp__#{safe_name}=(value)
|
42
22
|
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
43
|
-
|
23
|
+
#{sync_with_transaction_state}
|
24
|
+
_write_attribute(name, value)
|
44
25
|
end
|
45
26
|
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
|
46
27
|
undef_method :__temp__#{safe_name}=
|
47
28
|
STR
|
48
29
|
end
|
49
|
-
end
|
50
30
|
end
|
51
31
|
|
52
32
|
# Updates the attribute identified by <tt>attr_name</tt> with the
|
53
|
-
# specified +value+. Empty strings for
|
33
|
+
# specified +value+. Empty strings for Integer and Float columns are
|
54
34
|
# turned into +nil+.
|
55
35
|
def write_attribute(attr_name, value)
|
56
|
-
|
57
|
-
|
36
|
+
name = if self.class.attribute_alias?(attr_name)
|
37
|
+
self.class.attribute_alias(attr_name).to_s
|
38
|
+
else
|
39
|
+
attr_name.to_s
|
40
|
+
end
|
58
41
|
|
59
|
-
|
60
|
-
|
42
|
+
primary_key = self.class.primary_key
|
43
|
+
name = primary_key if name == "id".freeze && primary_key
|
44
|
+
sync_with_transaction_state if name == primary_key
|
45
|
+
_write_attribute(name, value)
|
61
46
|
end
|
62
47
|
|
63
|
-
|
64
|
-
#
|
65
|
-
def
|
66
|
-
|
48
|
+
# This method exists to avoid the expensive primary_key check internally, without
|
49
|
+
# breaking compatibility with the write_attribute API
|
50
|
+
def _write_attribute(attr_name, value) # :nodoc:
|
51
|
+
@attributes.write_from_user(attr_name.to_s, value)
|
52
|
+
value
|
67
53
|
end
|
68
54
|
|
69
|
-
|
70
|
-
attr_name
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
@attributes.write_from_user(attr_name, value)
|
75
|
-
else
|
76
|
-
@attributes.write_cast_value(attr_name, value)
|
55
|
+
private
|
56
|
+
def write_attribute_without_type_cast(attr_name, value)
|
57
|
+
name = attr_name.to_s
|
58
|
+
@attributes.write_cast_value(name, value)
|
59
|
+
value
|
77
60
|
end
|
78
61
|
|
79
|
-
|
80
|
-
|
62
|
+
# Handle *= for method_missing.
|
63
|
+
def attribute=(attribute_name, value)
|
64
|
+
_write_attribute(attribute_name, value)
|
65
|
+
end
|
81
66
|
end
|
82
67
|
end
|
83
68
|
end
|
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require 'thread_safe'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mutex_m"
|
5
4
|
|
6
5
|
module ActiveRecord
|
7
6
|
# = Active Record Attribute Methods
|
@@ -34,32 +33,10 @@ module ActiveRecord
|
|
34
33
|
|
35
34
|
BLACKLISTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
|
36
35
|
|
37
|
-
class
|
38
|
-
|
39
|
-
@module = Module.new
|
40
|
-
@method_cache = ThreadSafe::Cache.new
|
41
|
-
end
|
42
|
-
|
43
|
-
def [](name)
|
44
|
-
@method_cache.compute_if_absent(name) do
|
45
|
-
safe_name = name.unpack('h*').first
|
46
|
-
temp_method = "__temp__#{safe_name}"
|
47
|
-
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
48
|
-
@module.module_eval method_body(temp_method, safe_name), __FILE__, __LINE__
|
49
|
-
@module.instance_method temp_method
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
# Override this method in the subclasses for method body.
|
56
|
-
def method_body(method_name, const_name)
|
57
|
-
raise NotImplementedError, "Subclasses must implement a method_body(method_name, const_name) method."
|
58
|
-
end
|
36
|
+
class GeneratedAttributeMethods < Module #:nodoc:
|
37
|
+
include Mutex_m
|
59
38
|
end
|
60
39
|
|
61
|
-
class GeneratedAttributeMethods < Module; end # :nodoc:
|
62
|
-
|
63
40
|
module ClassMethods
|
64
41
|
def inherited(child_class) #:nodoc:
|
65
42
|
child_class.initialize_generated_modules
|
@@ -67,7 +44,7 @@ module ActiveRecord
|
|
67
44
|
end
|
68
45
|
|
69
46
|
def initialize_generated_modules # :nodoc:
|
70
|
-
@generated_attribute_methods = GeneratedAttributeMethods.new
|
47
|
+
@generated_attribute_methods = GeneratedAttributeMethods.new
|
71
48
|
@attribute_methods_generated = false
|
72
49
|
include @generated_attribute_methods
|
73
50
|
|
@@ -83,10 +60,9 @@ module ActiveRecord
|
|
83
60
|
generated_attribute_methods.synchronize do
|
84
61
|
return false if @attribute_methods_generated
|
85
62
|
superclass.define_attribute_methods unless self == base_class
|
86
|
-
super(
|
63
|
+
super(attribute_names)
|
87
64
|
@attribute_methods_generated = true
|
88
65
|
end
|
89
|
-
true
|
90
66
|
end
|
91
67
|
|
92
68
|
def undefine_attribute_methods # :nodoc:
|
@@ -96,7 +72,7 @@ module ActiveRecord
|
|
96
72
|
end
|
97
73
|
end
|
98
74
|
|
99
|
-
# Raises
|
75
|
+
# Raises an ActiveRecord::DangerousAttributeError exception when an
|
100
76
|
# \Active \Record method is defined in the model, otherwise +false+.
|
101
77
|
#
|
102
78
|
# class Person < ActiveRecord::Base
|
@@ -106,7 +82,7 @@ module ActiveRecord
|
|
106
82
|
# end
|
107
83
|
#
|
108
84
|
# Person.instance_method_already_implemented?(:save)
|
109
|
-
# # => ActiveRecord::DangerousAttributeError: save is defined by
|
85
|
+
# # => ActiveRecord::DangerousAttributeError: save is defined by Active Record. Check to make sure that you don't have an attribute or method with the same name.
|
110
86
|
#
|
111
87
|
# Person.instance_method_already_implemented?(:name)
|
112
88
|
# # => false
|
@@ -150,7 +126,7 @@ module ActiveRecord
|
|
150
126
|
BLACKLISTED_CLASS_METHODS.include?(method_name.to_s) || class_method_defined_within?(method_name, Base)
|
151
127
|
end
|
152
128
|
|
153
|
-
def class_method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc
|
129
|
+
def class_method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
|
154
130
|
if klass.respond_to?(name, true)
|
155
131
|
if superklass.respond_to?(name, true)
|
156
132
|
klass.method(name).owner != superklass.method(name).owner
|
@@ -172,7 +148,7 @@ module ActiveRecord
|
|
172
148
|
# Person.attribute_method?(:age=) # => true
|
173
149
|
# Person.attribute_method?(:nothing) # => false
|
174
150
|
def attribute_method?(attribute)
|
175
|
-
super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/,
|
151
|
+
super || (table_exists? && column_names.include?(attribute.to_s.sub(/=$/, "")))
|
176
152
|
end
|
177
153
|
|
178
154
|
# Returns an array of column names as strings if it's not an abstract class and
|
@@ -185,14 +161,78 @@ module ActiveRecord
|
|
185
161
|
# # => ["id", "created_at", "updated_at", "name", "age"]
|
186
162
|
def attribute_names
|
187
163
|
@attribute_names ||= if !abstract_class? && table_exists?
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
164
|
+
attribute_types.keys
|
165
|
+
else
|
166
|
+
[]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Regexp whitelist. Matches the following:
|
171
|
+
# "#{table_name}.#{column_name}"
|
172
|
+
# "#{column_name}"
|
173
|
+
COLUMN_NAME_WHITELIST = /\A(?:\w+\.)?\w+\z/i
|
174
|
+
|
175
|
+
# Regexp whitelist. Matches the following:
|
176
|
+
# "#{table_name}.#{column_name}"
|
177
|
+
# "#{table_name}.#{column_name} #{direction}"
|
178
|
+
# "#{table_name}.#{column_name} #{direction} NULLS FIRST"
|
179
|
+
# "#{table_name}.#{column_name} NULLS LAST"
|
180
|
+
# "#{column_name}"
|
181
|
+
# "#{column_name} #{direction}"
|
182
|
+
# "#{column_name} #{direction} NULLS FIRST"
|
183
|
+
# "#{column_name} NULLS LAST"
|
184
|
+
COLUMN_NAME_ORDER_WHITELIST = /
|
185
|
+
\A
|
186
|
+
(?:\w+\.)?
|
187
|
+
\w+
|
188
|
+
(?:\s+asc|\s+desc)?
|
189
|
+
(?:\s+nulls\s+(?:first|last))?
|
190
|
+
\z
|
191
|
+
/ix
|
192
|
+
|
193
|
+
def enforce_raw_sql_whitelist(args, whitelist: COLUMN_NAME_WHITELIST) # :nodoc:
|
194
|
+
unexpected = args.reject do |arg|
|
195
|
+
arg.kind_of?(Arel::Node) ||
|
196
|
+
arg.is_a?(Arel::Nodes::SqlLiteral) ||
|
197
|
+
arg.is_a?(Arel::Attributes::Attribute) ||
|
198
|
+
arg.to_s.split(/\s*,\s*/).all? { |part| whitelist.match?(part) }
|
199
|
+
end
|
200
|
+
|
201
|
+
return if unexpected.none?
|
202
|
+
|
203
|
+
if allow_unsafe_raw_sql == :deprecated
|
204
|
+
ActiveSupport::Deprecation.warn(
|
205
|
+
"Dangerous query method (method whose arguments are used as raw " \
|
206
|
+
"SQL) called with non-attribute argument(s): " \
|
207
|
+
"#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
|
208
|
+
"arguments will be disallowed in Rails 6.0. This method should " \
|
209
|
+
"not be called with user-provided values, such as request " \
|
210
|
+
"parameters or model attributes. Known-safe values can be passed " \
|
211
|
+
"by wrapping them in Arel.sql()."
|
212
|
+
)
|
213
|
+
else
|
214
|
+
raise(ActiveRecord::UnknownAttributeReference,
|
215
|
+
"Query method called with non-attribute argument(s): " +
|
216
|
+
unexpected.map(&:inspect).join(", ")
|
217
|
+
)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Returns true if the given attribute exists, otherwise false.
|
222
|
+
#
|
223
|
+
# class Person < ActiveRecord::Base
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# Person.has_attribute?('name') # => true
|
227
|
+
# Person.has_attribute?(:age) # => true
|
228
|
+
# Person.has_attribute?(:nothing) # => false
|
229
|
+
def has_attribute?(attr_name)
|
230
|
+
attribute_types.key?(attr_name.to_s)
|
192
231
|
end
|
193
232
|
|
194
233
|
# Returns the column object for the named attribute.
|
195
|
-
# Returns
|
234
|
+
# Returns a +ActiveRecord::ConnectionAdapters::NullColumn+ if the
|
235
|
+
# named attribute does not exist.
|
196
236
|
#
|
197
237
|
# class Person < ActiveRecord::Base
|
198
238
|
# end
|
@@ -202,39 +242,42 @@ module ActiveRecord
|
|
202
242
|
# # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
|
203
243
|
#
|
204
244
|
# person.column_for_attribute(:nothing)
|
205
|
-
# # => nil
|
245
|
+
# # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
|
206
246
|
def column_for_attribute(name)
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
`#column_for_attribute` will return a null object for non-existent
|
211
|
-
columns in Rails 5. Use `#has_attribute?` if you need to check for
|
212
|
-
an attribute's existence.
|
213
|
-
MSG
|
247
|
+
name = name.to_s
|
248
|
+
columns_hash.fetch(name) do
|
249
|
+
ConnectionAdapters::NullColumn.new(name)
|
214
250
|
end
|
215
|
-
column
|
216
251
|
end
|
217
252
|
end
|
218
253
|
|
219
254
|
# A Person object with a name attribute can ask <tt>person.respond_to?(:name)</tt>,
|
220
255
|
# <tt>person.respond_to?(:name=)</tt>, and <tt>person.respond_to?(:name?)</tt>
|
221
|
-
# which will all return +true+. It also
|
256
|
+
# which will all return +true+. It also defines the attribute methods if they have
|
222
257
|
# not been generated.
|
223
258
|
#
|
224
259
|
# class Person < ActiveRecord::Base
|
225
260
|
# end
|
226
261
|
#
|
227
262
|
# person = Person.new
|
228
|
-
# person.respond_to(:name) # => true
|
229
|
-
# person.respond_to(:name=) # => true
|
230
|
-
# person.respond_to(:name?) # => true
|
231
|
-
# person.respond_to('age') # => true
|
232
|
-
# person.respond_to('age=') # => true
|
233
|
-
# person.respond_to('age?') # => true
|
234
|
-
# person.respond_to(:nothing) # => false
|
263
|
+
# person.respond_to?(:name) # => true
|
264
|
+
# person.respond_to?(:name=) # => true
|
265
|
+
# person.respond_to?(:name?) # => true
|
266
|
+
# person.respond_to?('age') # => true
|
267
|
+
# person.respond_to?('age=') # => true
|
268
|
+
# person.respond_to?('age?') # => true
|
269
|
+
# person.respond_to?(:nothing) # => false
|
235
270
|
def respond_to?(name, include_private = false)
|
236
271
|
return false unless super
|
237
|
-
|
272
|
+
|
273
|
+
case name
|
274
|
+
when :to_partial_path
|
275
|
+
name = "to_partial_path".freeze
|
276
|
+
when :to_model
|
277
|
+
name = "to_model".freeze
|
278
|
+
else
|
279
|
+
name = name.to_s
|
280
|
+
end
|
238
281
|
|
239
282
|
# If the result is true then check for the select case.
|
240
283
|
# For queries selecting a subset of columns, return false for unselected columns.
|
@@ -244,7 +287,7 @@ module ActiveRecord
|
|
244
287
|
return has_attribute?(name)
|
245
288
|
end
|
246
289
|
|
247
|
-
|
290
|
+
true
|
248
291
|
end
|
249
292
|
|
250
293
|
# Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
|
@@ -287,9 +330,8 @@ module ActiveRecord
|
|
287
330
|
# Returns an <tt>#inspect</tt>-like string for the value of the
|
288
331
|
# attribute +attr_name+. String attributes are truncated up to 50
|
289
332
|
# characters, Date and Time attributes are returned in the
|
290
|
-
# <tt>:db</tt> format
|
291
|
-
#
|
292
|
-
# modification.
|
333
|
+
# <tt>:db</tt> format. Other attributes return the value of
|
334
|
+
# <tt>#inspect</tt> without modification.
|
293
335
|
#
|
294
336
|
# person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
|
295
337
|
#
|
@@ -300,7 +342,7 @@ module ActiveRecord
|
|
300
342
|
# # => "\"2012-10-22 00:15:07\""
|
301
343
|
#
|
302
344
|
# person.attribute_for_inspect(:tag_ids)
|
303
|
-
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
345
|
+
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
|
304
346
|
def attribute_for_inspect(attr_name)
|
305
347
|
value = read_attribute(attr_name)
|
306
348
|
|
@@ -308,9 +350,6 @@ module ActiveRecord
|
|
308
350
|
"#{value[0, 50]}...".inspect
|
309
351
|
elsif value.is_a?(Date) || value.is_a?(Time)
|
310
352
|
%("#{value.to_s(:db)}")
|
311
|
-
elsif value.is_a?(Array) && value.size > 10
|
312
|
-
inspected = value.first(10).inspect
|
313
|
-
%(#{inspected[0...-1]}, ...])
|
314
353
|
else
|
315
354
|
value.inspect
|
316
355
|
end
|
@@ -342,8 +381,6 @@ module ActiveRecord
|
|
342
381
|
#
|
343
382
|
# Note: +:id+ is always present.
|
344
383
|
#
|
345
|
-
# Alias for the <tt>read_attribute</tt> method.
|
346
|
-
#
|
347
384
|
# class Person < ActiveRecord::Base
|
348
385
|
# belongs_to :organization
|
349
386
|
# end
|
@@ -360,7 +397,7 @@ module ActiveRecord
|
|
360
397
|
end
|
361
398
|
|
362
399
|
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
|
363
|
-
# (Alias for the protected
|
400
|
+
# (Alias for the protected #write_attribute method).
|
364
401
|
#
|
365
402
|
# class Person < ActiveRecord::Base
|
366
403
|
# end
|
@@ -368,72 +405,88 @@ module ActiveRecord
|
|
368
405
|
# person = Person.new
|
369
406
|
# person[:age] = '22'
|
370
407
|
# person[:age] # => 22
|
371
|
-
# person[:age] # =>
|
408
|
+
# person[:age].class # => Integer
|
372
409
|
def []=(attr_name, value)
|
373
410
|
write_attribute(attr_name, value)
|
374
411
|
end
|
375
412
|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
413
|
+
# Returns the name of all database fields which have been read from this
|
414
|
+
# model. This can be useful in development mode to determine which fields
|
415
|
+
# need to be selected. For performance critical pages, selecting only the
|
416
|
+
# required fields can be an easy performance win (assuming you aren't using
|
417
|
+
# all of the fields on the model).
|
418
|
+
#
|
419
|
+
# For example:
|
420
|
+
#
|
421
|
+
# class PostsController < ActionController::Base
|
422
|
+
# after_action :print_accessed_fields, only: :index
|
423
|
+
#
|
424
|
+
# def index
|
425
|
+
# @posts = Post.all
|
426
|
+
# end
|
427
|
+
#
|
428
|
+
# private
|
429
|
+
#
|
430
|
+
# def print_accessed_fields
|
431
|
+
# p @posts.first.accessed_fields
|
432
|
+
# end
|
433
|
+
# end
|
434
|
+
#
|
435
|
+
# Which allows you to quickly change your code to:
|
436
|
+
#
|
437
|
+
# class PostsController < ActionController::Base
|
438
|
+
# def index
|
439
|
+
# @posts = Post.select(:id, :title, :author_id, :updated_at)
|
440
|
+
# end
|
441
|
+
# end
|
442
|
+
def accessed_fields
|
443
|
+
@attributes.accessed
|
387
444
|
end
|
388
445
|
|
389
|
-
|
390
|
-
arel_attributes_with_values(attributes_for_update(attribute_names))
|
391
|
-
end
|
446
|
+
protected
|
392
447
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
448
|
+
def attribute_method?(attr_name) # :nodoc:
|
449
|
+
# We check defined? because Syck calls respond_to? before actually calling initialize.
|
450
|
+
defined?(@attributes) && @attributes.key?(attr_name)
|
451
|
+
end
|
397
452
|
|
398
453
|
private
|
399
454
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
attrs = {}
|
404
|
-
arel_table = self.class.arel_table
|
455
|
+
def attributes_with_values_for_create(attribute_names)
|
456
|
+
attributes_with_values(attributes_for_create(attribute_names))
|
457
|
+
end
|
405
458
|
|
406
|
-
attribute_names
|
407
|
-
|
459
|
+
def attributes_with_values_for_update(attribute_names)
|
460
|
+
attributes_with_values(attributes_for_update(attribute_names))
|
408
461
|
end
|
409
|
-
attrs
|
410
|
-
end
|
411
462
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
463
|
+
def attributes_with_values(attribute_names)
|
464
|
+
attribute_names.each_with_object({}) do |name, attrs|
|
465
|
+
attrs[name] = _read_attribute(name)
|
466
|
+
end
|
416
467
|
end
|
417
|
-
end
|
418
468
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
469
|
+
# Filters the primary keys and readonly attributes from the attribute names.
|
470
|
+
def attributes_for_update(attribute_names)
|
471
|
+
attribute_names.reject do |name|
|
472
|
+
readonly_attribute?(name)
|
473
|
+
end
|
424
474
|
end
|
425
|
-
end
|
426
475
|
|
427
|
-
|
428
|
-
|
429
|
-
|
476
|
+
# Filters out the primary keys, from the attribute names, when the primary
|
477
|
+
# key is to be generated (e.g. the id attribute has no value).
|
478
|
+
def attributes_for_create(attribute_names)
|
479
|
+
attribute_names.reject do |name|
|
480
|
+
pk_attribute?(name) && id.nil?
|
481
|
+
end
|
482
|
+
end
|
430
483
|
|
431
|
-
|
432
|
-
|
433
|
-
|
484
|
+
def readonly_attribute?(name)
|
485
|
+
self.class.readonly_attributes.include?(name)
|
486
|
+
end
|
434
487
|
|
435
|
-
|
436
|
-
|
437
|
-
|
488
|
+
def pk_attribute?(name)
|
489
|
+
name == self.class.primary_key
|
490
|
+
end
|
438
491
|
end
|
439
492
|
end
|