activerecord 3.2.19 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1715 -604
- data/MIT-LICENSE +2 -2
- data/README.rdoc +40 -45
- data/examples/performance.rb +33 -22
- data/examples/simple.rb +3 -4
- data/lib/active_record/aggregations.rb +76 -51
- data/lib/active_record/association_relation.rb +35 -0
- data/lib/active_record/associations/alias_tracker.rb +54 -40
- data/lib/active_record/associations/association.rb +76 -56
- data/lib/active_record/associations/association_scope.rb +125 -93
- data/lib/active_record/associations/belongs_to_association.rb +57 -28
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
- data/lib/active_record/associations/builder/association.rb +120 -32
- data/lib/active_record/associations/builder/belongs_to.rb +115 -62
- data/lib/active_record/associations/builder/collection_association.rb +61 -53
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +117 -43
- data/lib/active_record/associations/builder/has_many.rb +9 -65
- data/lib/active_record/associations/builder/has_one.rb +18 -52
- data/lib/active_record/associations/builder/singular_association.rb +18 -19
- data/lib/active_record/associations/collection_association.rb +268 -186
- data/lib/active_record/associations/collection_proxy.rb +1003 -63
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +81 -41
- data/lib/active_record/associations/has_many_through_association.rb +76 -55
- data/lib/active_record/associations/has_one_association.rb +51 -21
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +83 -108
- data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
- data/lib/active_record/associations/join_dependency.rb +239 -155
- data/lib/active_record/associations/preloader/association.rb +97 -62
- data/lib/active_record/associations/preloader/collection_association.rb +2 -8
- data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/singular_association.rb +3 -3
- data/lib/active_record/associations/preloader/through_association.rb +75 -33
- data/lib/active_record/associations/preloader.rb +111 -79
- data/lib/active_record/associations/singular_association.rb +35 -13
- data/lib/active_record/associations/through_association.rb +41 -19
- data/lib/active_record/associations.rb +727 -501
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +213 -0
- data/lib/active_record/attribute_assignment.rb +32 -162
- data/lib/active_record/attribute_decorators.rb +67 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -61
- data/lib/active_record/attribute_methods/primary_key.rb +50 -36
- data/lib/active_record/attribute_methods/query.rb +7 -6
- data/lib/active_record/attribute_methods/read.rb +56 -117
- data/lib/active_record/attribute_methods/serialization.rb +43 -96
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +93 -42
- data/lib/active_record/attribute_methods/write.rb +34 -45
- data/lib/active_record/attribute_methods.rb +333 -144
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +108 -0
- data/lib/active_record/attribute_set.rb +108 -0
- data/lib/active_record/attributes.rb +265 -0
- data/lib/active_record/autosave_association.rb +285 -223
- data/lib/active_record/base.rb +95 -490
- data/lib/active_record/callbacks.rb +95 -61
- data/lib/active_record/coders/json.rb +13 -0
- data/lib/active_record/coders/yaml_column.rb +28 -19
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +724 -277
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -192
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -26
- data/lib/active_record/connection_adapters/abstract/quoting.rb +140 -57
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +147 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +419 -276
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +105 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +963 -276
- data/lib/active_record/connection_adapters/abstract/transaction.rb +232 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +397 -106
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +643 -342
- data/lib/active_record/connection_adapters/column.rb +30 -259
- data/lib/active_record/connection_adapters/connection_specification.rb +263 -0
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +47 -196
- data/lib/active_record/connection_adapters/postgresql/column.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +170 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +70 -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 +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +48 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -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/json.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +39 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +93 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -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 +31 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +116 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +180 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +682 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -1039
- data/lib/active_record/connection_adapters/schema_cache.rb +74 -36
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +538 -24
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +155 -0
- data/lib/active_record/core.rb +561 -0
- data/lib/active_record/counter_cache.rb +146 -105
- data/lib/active_record/dynamic_matchers.rb +101 -64
- data/lib/active_record/enum.rb +234 -0
- data/lib/active_record/errors.rb +153 -56
- data/lib/active_record/explain.rb +15 -63
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +10 -6
- data/lib/active_record/fixture_set/file.rb +77 -0
- data/lib/active_record/fixtures.rb +355 -232
- data/lib/active_record/gem_version.rb +15 -0
- data/lib/active_record/inheritance.rb +144 -79
- data/lib/active_record/integration.rb +66 -13
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +46 -0
- data/lib/active_record/locale/en.yml +9 -1
- data/lib/active_record/locking/optimistic.rb +77 -56
- data/lib/active_record/locking/pessimistic.rb +6 -6
- data/lib/active_record/log_subscriber.rb +53 -28
- data/lib/active_record/migration/command_recorder.rb +166 -33
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +792 -264
- data/lib/active_record/model_schema.rb +192 -130
- data/lib/active_record/nested_attributes.rb +238 -145
- data/lib/active_record/no_touching.rb +52 -0
- data/lib/active_record/null_relation.rb +89 -0
- data/lib/active_record/persistence.rb +357 -157
- data/lib/active_record/query_cache.rb +22 -43
- data/lib/active_record/querying.rb +34 -23
- data/lib/active_record/railtie.rb +88 -48
- data/lib/active_record/railties/console_sandbox.rb +3 -4
- data/lib/active_record/railties/controller_runtime.rb +5 -4
- data/lib/active_record/railties/databases.rake +170 -422
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -5
- data/lib/active_record/reflection.rb +715 -189
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +203 -50
- data/lib/active_record/relation/calculations.rb +203 -194
- data/lib/active_record/relation/delegation.rb +103 -25
- data/lib/active_record/relation/finder_methods.rb +457 -261
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +167 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +43 -0
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
- data/lib/active_record/relation/predicate_builder.rb +153 -48
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +1019 -194
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +46 -150
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/relation.rb +450 -245
- data/lib/active_record/result.rb +104 -12
- data/lib/active_record/runtime_registry.rb +22 -0
- data/lib/active_record/sanitization.rb +120 -94
- data/lib/active_record/schema.rb +28 -18
- data/lib/active_record/schema_dumper.rb +141 -74
- data/lib/active_record/schema_migration.rb +50 -0
- data/lib/active_record/scoping/default.rb +64 -57
- data/lib/active_record/scoping/named.rb +93 -108
- data/lib/active_record/scoping.rb +73 -121
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +7 -5
- data/lib/active_record/statement_cache.rb +113 -0
- data/lib/active_record/store.rb +173 -15
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +313 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +151 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +110 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +59 -0
- data/lib/active_record/timestamp.rb +42 -24
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +233 -105
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +7 -0
- data/lib/active_record/type/date_time.rb +7 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
- data/lib/active_record/type/internal/abstract_json.rb +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +63 -0
- data/lib/active_record/type/time.rb +20 -0
- data/lib/active_record/type/type_map.rb +64 -0
- data/lib/active_record/type.rb +72 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +33 -18
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +66 -0
- data/lib/active_record/validations/uniqueness.rb +128 -68
- data/lib/active_record/validations.rb +48 -40
- data/lib/active_record/version.rb +5 -7
- data/lib/active_record.rb +71 -47
- data/lib/rails/generators/active_record/migration/migration_generator.rb +56 -8
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +24 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +28 -16
- data/lib/rails/generators/active_record/migration.rb +18 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -16
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +7 -6
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- data/lib/rails/generators/active_record.rb +3 -11
- metadata +188 -134
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/serializers/xml_serializer.rb +0 -203
- data/lib/active_record/session_store.rb +0 -360
- data/lib/active_record/test_case.rb +0 -73
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class HashLookupTypeMap < TypeMap # :nodoc:
|
4
|
+
def alias_type(type, alias_type)
|
5
|
+
register_type(type) { |_, *args| lookup(alias_type, *args) }
|
6
|
+
end
|
7
|
+
|
8
|
+
def key?(key)
|
9
|
+
@mapping.key?(key)
|
10
|
+
end
|
11
|
+
|
12
|
+
def keys
|
13
|
+
@mapping.keys
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def perform_fetch(type, *args, &block)
|
19
|
+
@mapping.fetch(type, block).call(type, *args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
module Internal # :nodoc:
|
4
|
+
class AbstractJson < ActiveModel::Type::Value # :nodoc:
|
5
|
+
include ActiveModel::Type::Helpers::Mutable
|
6
|
+
|
7
|
+
def type
|
8
|
+
:json
|
9
|
+
end
|
10
|
+
|
11
|
+
def deserialize(value)
|
12
|
+
if value.is_a?(::String)
|
13
|
+
::ActiveSupport::JSON.decode(value) rescue nil
|
14
|
+
else
|
15
|
+
value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def serialize(value)
|
20
|
+
::ActiveSupport::JSON.encode(value)
|
21
|
+
end
|
22
|
+
|
23
|
+
def accessor
|
24
|
+
ActiveRecord::Store::StringKeyedHashAccessor
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc:
|
4
|
+
include ActiveModel::Type::Helpers::Mutable
|
5
|
+
|
6
|
+
attr_reader :subtype, :coder
|
7
|
+
|
8
|
+
def initialize(subtype, coder)
|
9
|
+
@subtype = subtype
|
10
|
+
@coder = coder
|
11
|
+
super(subtype)
|
12
|
+
end
|
13
|
+
|
14
|
+
def deserialize(value)
|
15
|
+
if default_value?(value)
|
16
|
+
value
|
17
|
+
else
|
18
|
+
coder.load(super)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def serialize(value)
|
23
|
+
return if value.nil?
|
24
|
+
unless default_value?(value)
|
25
|
+
super coder.dump(value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
Kernel.instance_method(:inspect).bind(self).call
|
31
|
+
end
|
32
|
+
|
33
|
+
def changed_in_place?(raw_old_value, value)
|
34
|
+
return false if value.nil?
|
35
|
+
raw_new_value = encoded(value)
|
36
|
+
raw_old_value.nil? != raw_new_value.nil? ||
|
37
|
+
subtype.changed_in_place?(raw_old_value, raw_new_value)
|
38
|
+
end
|
39
|
+
|
40
|
+
def accessor
|
41
|
+
ActiveRecord::Store::IndifferentHashAccessor
|
42
|
+
end
|
43
|
+
|
44
|
+
def assert_valid_value(value)
|
45
|
+
if coder.respond_to?(:assert_valid_value)
|
46
|
+
coder.assert_valid_value(value)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def default_value?(value)
|
53
|
+
value == coder.load(nil)
|
54
|
+
end
|
55
|
+
|
56
|
+
def encoded(value)
|
57
|
+
unless default_value?(value)
|
58
|
+
coder.dump(value)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class Time < ActiveModel::Type::Time
|
4
|
+
include Internal::Timezone
|
5
|
+
|
6
|
+
class Value < DelegateClass(::Time) # :nodoc:
|
7
|
+
end
|
8
|
+
|
9
|
+
def serialize(value)
|
10
|
+
case value = super
|
11
|
+
when ::Time
|
12
|
+
Value.new(value)
|
13
|
+
else
|
14
|
+
value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'concurrent/map'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Type
|
5
|
+
class TypeMap # :nodoc:
|
6
|
+
def initialize
|
7
|
+
@mapping = {}
|
8
|
+
@cache = Concurrent::Map.new do |h, key|
|
9
|
+
h.fetch_or_store(key, Concurrent::Map.new)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def lookup(lookup_key, *args)
|
14
|
+
fetch(lookup_key, *args) { default_value }
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch(lookup_key, *args, &block)
|
18
|
+
@cache[lookup_key].fetch_or_store(args) do
|
19
|
+
perform_fetch(lookup_key, *args, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def register_type(key, value = nil, &block)
|
24
|
+
raise ::ArgumentError unless value || block
|
25
|
+
@cache.clear
|
26
|
+
|
27
|
+
if block
|
28
|
+
@mapping[key] = block
|
29
|
+
else
|
30
|
+
@mapping[key] = proc { value }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def alias_type(key, target_key)
|
35
|
+
register_type(key) do |sql_type, *args|
|
36
|
+
metadata = sql_type[/\(.*\)/, 0]
|
37
|
+
lookup("#{target_key}#{metadata}", *args)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def clear
|
42
|
+
@mapping.clear
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def perform_fetch(lookup_key, *args)
|
48
|
+
matching_pair = @mapping.reverse_each.detect do |key, _|
|
49
|
+
key === lookup_key
|
50
|
+
end
|
51
|
+
|
52
|
+
if matching_pair
|
53
|
+
matching_pair.last.call(lookup_key, *args)
|
54
|
+
else
|
55
|
+
yield lookup_key, *args
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_value
|
60
|
+
@default_value ||= ActiveModel::Type::Value.new
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'active_model/type'
|
2
|
+
|
3
|
+
require 'active_record/type/internal/abstract_json'
|
4
|
+
require 'active_record/type/internal/timezone'
|
5
|
+
|
6
|
+
require 'active_record/type/date'
|
7
|
+
require 'active_record/type/date_time'
|
8
|
+
require 'active_record/type/time'
|
9
|
+
|
10
|
+
require 'active_record/type/serialized'
|
11
|
+
require 'active_record/type/adapter_specific_registry'
|
12
|
+
|
13
|
+
require 'active_record/type/type_map'
|
14
|
+
require 'active_record/type/hash_lookup_type_map'
|
15
|
+
|
16
|
+
module ActiveRecord
|
17
|
+
module Type
|
18
|
+
@registry = AdapterSpecificRegistry.new
|
19
|
+
|
20
|
+
class << self
|
21
|
+
attr_accessor :registry # :nodoc:
|
22
|
+
delegate :add_modifier, to: :registry
|
23
|
+
|
24
|
+
# Add a new type to the registry, allowing it to be referenced as a
|
25
|
+
# symbol by {ActiveRecord::Base.attribute}[rdoc-ref:Attributes::ClassMethods#attribute].
|
26
|
+
# If your type is only meant to be used with a specific database adapter, you can
|
27
|
+
# do so by passing <tt>adapter: :postgresql</tt>. If your type has the same
|
28
|
+
# name as a native type for the current adapter, an exception will be
|
29
|
+
# raised unless you specify an +:override+ option. <tt>override: true</tt> will
|
30
|
+
# cause your type to be used instead of the native type. <tt>override:
|
31
|
+
# false</tt> will cause the native type to be used over yours if one exists.
|
32
|
+
def register(type_name, klass = nil, **options, &block)
|
33
|
+
registry.register(type_name, klass, **options, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def lookup(*args, adapter: current_adapter_name, **kwargs) # :nodoc:
|
37
|
+
registry.lookup(*args, adapter: adapter, **kwargs)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def current_adapter_name
|
43
|
+
ActiveRecord::Base.connection.adapter_name.downcase.to_sym
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Helpers = ActiveModel::Type::Helpers
|
48
|
+
BigInteger = ActiveModel::Type::BigInteger
|
49
|
+
Binary = ActiveModel::Type::Binary
|
50
|
+
Boolean = ActiveModel::Type::Boolean
|
51
|
+
Decimal = ActiveModel::Type::Decimal
|
52
|
+
DecimalWithoutScale = ActiveModel::Type::DecimalWithoutScale
|
53
|
+
Float = ActiveModel::Type::Float
|
54
|
+
Integer = ActiveModel::Type::Integer
|
55
|
+
String = ActiveModel::Type::String
|
56
|
+
Text = ActiveModel::Type::Text
|
57
|
+
UnsignedInteger = ActiveModel::Type::UnsignedInteger
|
58
|
+
Value = ActiveModel::Type::Value
|
59
|
+
|
60
|
+
register(:big_integer, Type::BigInteger, override: false)
|
61
|
+
register(:binary, Type::Binary, override: false)
|
62
|
+
register(:boolean, Type::Boolean, override: false)
|
63
|
+
register(:date, Type::Date, override: false)
|
64
|
+
register(:datetime, Type::DateTime, override: false)
|
65
|
+
register(:decimal, Type::Decimal, override: false)
|
66
|
+
register(:float, Type::Float, override: false)
|
67
|
+
register(:integer, Type::Integer, override: false)
|
68
|
+
register(:string, Type::String, override: false)
|
69
|
+
register(:text, Type::Text, override: false)
|
70
|
+
register(:time, Type::Time, override: false)
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module TypeCaster
|
3
|
+
class Connection # :nodoc:
|
4
|
+
def initialize(klass, table_name)
|
5
|
+
@klass = klass
|
6
|
+
@table_name = table_name
|
7
|
+
end
|
8
|
+
|
9
|
+
def type_cast_for_database(attribute_name, value)
|
10
|
+
return value if value.is_a?(Arel::Nodes::BindParam)
|
11
|
+
column = column_for(attribute_name)
|
12
|
+
connection.type_cast_from_column(column, value)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
attr_reader :table_name
|
18
|
+
delegate :connection, to: :@klass
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def column_for(attribute_name)
|
23
|
+
if connection.schema_cache.data_source_exists?(table_name)
|
24
|
+
connection.schema_cache.columns_hash(table_name)[attribute_name.to_s]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module TypeCaster
|
3
|
+
class Map # :nodoc:
|
4
|
+
def initialize(types)
|
5
|
+
@types = types
|
6
|
+
end
|
7
|
+
|
8
|
+
def type_cast_for_database(attr_name, value)
|
9
|
+
return value if value.is_a?(Arel::Nodes::BindParam)
|
10
|
+
type = types.type_for_attribute(attr_name.to_s)
|
11
|
+
type.serialize(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
attr_reader :types
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Validations
|
3
|
+
class AbsenceValidator < ActiveModel::Validations::AbsenceValidator # :nodoc:
|
4
|
+
def validate_each(record, attribute, association_or_value)
|
5
|
+
if record.class._reflect_on_association(attribute)
|
6
|
+
association_or_value = Array.wrap(association_or_value).reject(&:marked_for_destruction?)
|
7
|
+
end
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Validates that the specified attributes are not present (as defined by
|
14
|
+
# Object#present?). If the attribute is an association, the associated object
|
15
|
+
# is considered absent if it was marked for destruction.
|
16
|
+
#
|
17
|
+
# See ActiveModel::Validations::HelperMethods.validates_absence_of for more information.
|
18
|
+
def validates_absence_of(*attr_names)
|
19
|
+
validates_with AbsenceValidator, _merge_attributes(attr_names)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,15 +1,22 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Validations
|
3
|
-
class AssociatedValidator < ActiveModel::EachValidator
|
3
|
+
class AssociatedValidator < ActiveModel::EachValidator #:nodoc:
|
4
4
|
def validate_each(record, attribute, value)
|
5
|
-
if Array
|
6
|
-
record.errors.add(attribute, :invalid, options.merge(:
|
5
|
+
if Array(value).reject { |r| valid_object?(r) }.any?
|
6
|
+
record.errors.add(attribute, :invalid, options.merge(value: value))
|
7
7
|
end
|
8
8
|
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def valid_object?(record)
|
13
|
+
(record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid?
|
14
|
+
end
|
9
15
|
end
|
10
16
|
|
11
17
|
module ClassMethods
|
12
|
-
# Validates whether the associated object or objects are all valid
|
18
|
+
# Validates whether the associated object or objects are all valid.
|
19
|
+
# Works with any kind of association.
|
13
20
|
#
|
14
21
|
# class Book < ActiveRecord::Base
|
15
22
|
# has_many :pages
|
@@ -18,23 +25,31 @@ module ActiveRecord
|
|
18
25
|
# validates_associated :pages, :library
|
19
26
|
# end
|
20
27
|
#
|
21
|
-
# WARNING: This validation must not be used on both ends of an association.
|
28
|
+
# WARNING: This validation must not be used on both ends of an association.
|
29
|
+
# Doing so will lead to a circular dependency and cause infinite recursion.
|
22
30
|
#
|
23
|
-
# NOTE: This validation will not fail if the association hasn't been
|
24
|
-
# ensure that the association is both present and
|
25
|
-
# use
|
31
|
+
# NOTE: This validation will not fail if the association hasn't been
|
32
|
+
# assigned. If you want to ensure that the association is both present and
|
33
|
+
# guaranteed to be valid, you also need to use
|
34
|
+
# {validates_presence_of}[rdoc-ref:Validations::ClassMethods#validates_presence_of].
|
26
35
|
#
|
27
36
|
# Configuration options:
|
28
|
-
#
|
29
|
-
# * <tt>:
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# * <tt>:
|
36
|
-
#
|
37
|
-
#
|
37
|
+
#
|
38
|
+
# * <tt>:message</tt> - A custom error message (default is: "is invalid").
|
39
|
+
# * <tt>:on</tt> - Specifies the contexts where this validation is active.
|
40
|
+
# Runs in all validation contexts by default (nil). You can pass a symbol
|
41
|
+
# or an array of symbols. (e.g. <tt>on: :create</tt> or
|
42
|
+
# <tt>on: :custom_validation_context</tt> or
|
43
|
+
# <tt>on: [:create, :custom_validation_context]</tt>)
|
44
|
+
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
|
45
|
+
# if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
|
46
|
+
# or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
|
47
|
+
# proc or string should return or evaluate to a +true+ or +false+ value.
|
48
|
+
# * <tt>:unless</tt> - Specifies a method, proc or string to call to
|
49
|
+
# determine if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
|
50
|
+
# or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
|
51
|
+
# method, proc or string should return or evaluate to a +true+ or +false+
|
52
|
+
# value.
|
38
53
|
def validates_associated(*attr_names)
|
39
54
|
validates_with AssociatedValidator, _merge_attributes(attr_names)
|
40
55
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Validations
|
3
|
+
class LengthValidator < ActiveModel::Validations::LengthValidator # :nodoc:
|
4
|
+
def validate_each(record, attribute, association_or_value)
|
5
|
+
if association_or_value.respond_to?(:loaded?) && association_or_value.loaded?
|
6
|
+
association_or_value = association_or_value.target.reject(&:marked_for_destruction?)
|
7
|
+
end
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Validates that the specified attributes match the length restrictions supplied.
|
14
|
+
# If the attribute is an association, records that are marked for destruction are not counted.
|
15
|
+
#
|
16
|
+
# See ActiveModel::Validations::HelperMethods.validates_length_of for more information.
|
17
|
+
def validates_length_of(*attr_names)
|
18
|
+
validates_with LengthValidator, _merge_attributes(attr_names)
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :validates_size_of, :validates_length_of
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Validations
|
3
|
+
class PresenceValidator < ActiveModel::Validations::PresenceValidator # :nodoc:
|
4
|
+
def validate_each(record, attribute, association_or_value)
|
5
|
+
if record.class._reflect_on_association(attribute)
|
6
|
+
association_or_value = Array.wrap(association_or_value).reject(&:marked_for_destruction?)
|
7
|
+
end
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Validates that the specified attributes are not blank (as defined by
|
14
|
+
# Object#blank?), and, if the attribute is an association, that the
|
15
|
+
# associated object is not marked for destruction. Happens by default
|
16
|
+
# on save.
|
17
|
+
#
|
18
|
+
# class Person < ActiveRecord::Base
|
19
|
+
# has_one :face
|
20
|
+
# validates_presence_of :face
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# The face attribute must be in the object and it cannot be blank or marked
|
24
|
+
# for destruction.
|
25
|
+
#
|
26
|
+
# If you want to validate the presence of a boolean field (where the real values
|
27
|
+
# are true and false), you will want to use
|
28
|
+
# <tt>validates_inclusion_of :field_name, in: [true, false]</tt>.
|
29
|
+
#
|
30
|
+
# This is due to the way Object#blank? handles boolean values:
|
31
|
+
# <tt>false.blank? # => true</tt>.
|
32
|
+
#
|
33
|
+
# This validator defers to the Active Model validation for presence, adding the
|
34
|
+
# check to see that an associated object is not marked for destruction. This
|
35
|
+
# prevents the parent object from validating successfully and saving, which then
|
36
|
+
# deletes the associated object, thus putting the parent object into an invalid
|
37
|
+
# state.
|
38
|
+
#
|
39
|
+
# NOTE: This validation will not fail while using it with an association
|
40
|
+
# if the latter was assigned but not valid. If you want to ensure that
|
41
|
+
# it is both present and valid, you also need to use
|
42
|
+
# {validates_associated}[rdoc-ref:Validations::ClassMethods#validates_associated].
|
43
|
+
#
|
44
|
+
# Configuration options:
|
45
|
+
# * <tt>:message</tt> - A custom error message (default is: "can't be blank").
|
46
|
+
# * <tt>:on</tt> - Specifies the contexts where this validation is active.
|
47
|
+
# Runs in all validation contexts by default (nil). You can pass a symbol
|
48
|
+
# or an array of symbols. (e.g. <tt>on: :create</tt> or
|
49
|
+
# <tt>on: :custom_validation_context</tt> or
|
50
|
+
# <tt>on: [:create, :custom_validation_context]</tt>)
|
51
|
+
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if
|
52
|
+
# the validation should occur (e.g. <tt>if: :allow_validation</tt>, or
|
53
|
+
# <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
|
54
|
+
# or string should return or evaluate to a +true+ or +false+ value.
|
55
|
+
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
|
56
|
+
# if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
|
57
|
+
# or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
|
58
|
+
# proc or string should return or evaluate to a +true+ or +false+ value.
|
59
|
+
# * <tt>:strict</tt> - Specifies whether validation should be strict.
|
60
|
+
# See ActiveModel::Validation#validates! for more information.
|
61
|
+
def validates_presence_of(*attr_names)
|
62
|
+
validates_with PresenceValidator, _merge_attributes(attr_names)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|