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.
- 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
|