activerecord 4.2.6 → 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 +4 -4
- data/CHANGELOG.md +1307 -1105
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record/aggregations.rb +37 -23
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +11 -9
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +50 -31
- data/lib/active_record/associations/collection_proxy.rb +69 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
- data/lib/active_record/associations/join_dependency.rb +29 -19
- data/lib/active_record/associations/preloader/association.rb +46 -52
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +27 -14
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/associations.rb +317 -209
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +68 -18
- data/lib/active_record/attribute_assignment.rb +20 -141
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attributes.rb +199 -80
- data/lib/active_record/autosave_association.rb +49 -16
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -140
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +153 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -362
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- 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 +25 -176
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- 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 +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- 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 +148 -203
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +89 -107
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +113 -76
- data/lib/active_record/errors.rb +87 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +364 -109
- data/lib/active_record/model_schema.rb +128 -38
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +121 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +27 -18
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +58 -45
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +282 -115
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +80 -102
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +163 -81
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -15
- 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 +1 -1
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- 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 +176 -116
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -17
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- 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 +58 -41
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -20
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -41
- data/lib/active_record/type/date_time.rb +2 -49
- 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 +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type.rb +66 -17
- 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 +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +30 -29
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +7 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +58 -34
- 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/date.rb +0 -11
- 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/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- 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 -31
- data/lib/active_record/type/decimal.rb +0 -50
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- 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 -59
- 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 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -105
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
def replace(record)
|
11
11
|
if record
|
12
12
|
raise_on_type_mismatch!(record)
|
13
|
-
|
13
|
+
update_counters_on_replace(record)
|
14
14
|
replace_keys(record)
|
15
15
|
set_inverse_instance(record)
|
16
16
|
@updated = true
|
@@ -32,45 +32,38 @@ module ActiveRecord
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def decrement_counters # :nodoc:
|
35
|
-
|
35
|
+
update_counters(-1)
|
36
36
|
end
|
37
37
|
|
38
38
|
def increment_counters # :nodoc:
|
39
|
-
|
39
|
+
update_counters(1)
|
40
40
|
end
|
41
41
|
|
42
42
|
private
|
43
43
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
44
|
+
def update_counters(by)
|
45
|
+
if require_counter_update? && foreign_key_present?
|
46
|
+
if target && !stale_target?
|
47
|
+
target.increment!(reflection.counter_cache_column, by)
|
48
|
+
else
|
49
|
+
klass.update_counters(target_id, reflection.counter_cache_column => by)
|
50
|
+
end
|
51
|
+
end
|
52
52
|
end
|
53
53
|
|
54
|
-
def
|
55
|
-
|
56
|
-
return unless different_target? record
|
57
|
-
record.class.increment_counter(name, record.id)
|
58
|
-
decrement_counter name
|
59
|
-
end
|
54
|
+
def find_target?
|
55
|
+
!loaded? && foreign_key_present? && klass
|
60
56
|
end
|
61
57
|
|
62
|
-
def
|
63
|
-
|
64
|
-
klass.decrement_counter(counter_cache_name, target_id)
|
65
|
-
end
|
58
|
+
def require_counter_update?
|
59
|
+
reflection.counter_cache_column && owner.persisted?
|
66
60
|
end
|
67
61
|
|
68
|
-
def
|
69
|
-
if
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
62
|
+
def update_counters_on_replace(record)
|
63
|
+
if require_counter_update? && different_target?(record)
|
64
|
+
owner.instance_variable_set :@_after_replace_counter_called, true
|
65
|
+
record.increment!(reflection.counter_cache_column)
|
66
|
+
decrement_counters
|
74
67
|
end
|
75
68
|
end
|
76
69
|
|
@@ -107,13 +100,9 @@ module ActiveRecord
|
|
107
100
|
end
|
108
101
|
|
109
102
|
def stale_state
|
110
|
-
result = owner._read_attribute(reflection.foreign_key)
|
103
|
+
result = owner._read_attribute(reflection.foreign_key) { |n| owner.send(:missing_attribute, n, caller) }
|
111
104
|
result && result.to_s
|
112
105
|
end
|
113
|
-
|
114
|
-
def counter_cache_available_in_memory?(counter_cache_name)
|
115
|
-
target.respond_to?(counter_cache_name)
|
116
|
-
end
|
117
106
|
end
|
118
107
|
end
|
119
108
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
-
|
3
1
|
# This is the parent Association class which defines the variables
|
4
2
|
# used by all associations.
|
5
3
|
#
|
@@ -11,19 +9,14 @@ require 'active_support/core_ext/module/attribute_accessors'
|
|
11
9
|
# - CollectionAssociation
|
12
10
|
# - HasManyAssociation
|
13
11
|
|
14
|
-
module ActiveRecord::Associations::Builder
|
12
|
+
module ActiveRecord::Associations::Builder # :nodoc:
|
15
13
|
class Association #:nodoc:
|
16
14
|
class << self
|
17
15
|
attr_accessor :extensions
|
18
|
-
# TODO: This class accessor is needed to make activerecord-deprecated_finders work.
|
19
|
-
# We can move it to a constant in 5.0.
|
20
|
-
attr_accessor :valid_options
|
21
16
|
end
|
22
17
|
self.extensions = []
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
attr_reader :name, :scope, :options
|
19
|
+
VALID_OPTIONS = [:class_name, :anonymous_class, :foreign_key, :validate] # :nodoc:
|
27
20
|
|
28
21
|
def self.build(model, name, scope, options, &block)
|
29
22
|
if model.dangerous_attribute_method?(name)
|
@@ -32,57 +25,60 @@ module ActiveRecord::Associations::Builder
|
|
32
25
|
"Please choose a different association name."
|
33
26
|
end
|
34
27
|
|
35
|
-
|
36
|
-
reflection =
|
28
|
+
extension = define_extensions model, name, &block
|
29
|
+
reflection = create_reflection model, name, scope, options, extension
|
37
30
|
define_accessors model, reflection
|
38
31
|
define_callbacks model, reflection
|
39
32
|
define_validations model, reflection
|
40
|
-
builder.define_extensions model
|
41
33
|
reflection
|
42
34
|
end
|
43
35
|
|
44
|
-
def self.
|
36
|
+
def self.create_reflection(model, name, scope, options, extension = nil)
|
45
37
|
raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol)
|
46
38
|
|
47
|
-
new(model, name, scope, options, &block)
|
48
|
-
end
|
49
|
-
|
50
|
-
def initialize(model, name, scope, options)
|
51
|
-
# TODO: Move this to create_builder as soon we drop support to activerecord-deprecated_finders.
|
52
39
|
if scope.is_a?(Hash)
|
53
40
|
options = scope
|
54
41
|
scope = nil
|
55
42
|
end
|
56
43
|
|
57
|
-
|
58
|
-
@name = name
|
59
|
-
@scope = scope
|
60
|
-
@options = options
|
44
|
+
validate_options(options)
|
61
45
|
|
62
|
-
|
46
|
+
scope = build_scope(scope, extension)
|
47
|
+
|
48
|
+
ActiveRecord::Reflection.create(macro, name, scope, options, model)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.build_scope(scope, extension)
|
52
|
+
new_scope = scope
|
63
53
|
|
64
54
|
if scope && scope.arity == 0
|
65
|
-
|
55
|
+
new_scope = proc { instance_exec(&scope) }
|
56
|
+
end
|
57
|
+
|
58
|
+
if extension
|
59
|
+
new_scope = wrap_scope new_scope, extension
|
66
60
|
end
|
61
|
+
|
62
|
+
new_scope
|
67
63
|
end
|
68
64
|
|
69
|
-
def
|
70
|
-
|
65
|
+
def self.wrap_scope(scope, extension)
|
66
|
+
scope
|
71
67
|
end
|
72
68
|
|
73
|
-
def macro
|
69
|
+
def self.macro
|
74
70
|
raise NotImplementedError
|
75
71
|
end
|
76
72
|
|
77
|
-
def valid_options
|
78
|
-
|
73
|
+
def self.valid_options(options)
|
74
|
+
VALID_OPTIONS + Association.extensions.flat_map(&:valid_options)
|
79
75
|
end
|
80
76
|
|
81
|
-
def validate_options
|
82
|
-
options.assert_valid_keys(valid_options)
|
77
|
+
def self.validate_options(options)
|
78
|
+
options.assert_valid_keys(valid_options(options))
|
83
79
|
end
|
84
80
|
|
85
|
-
def define_extensions(model)
|
81
|
+
def self.define_extensions(model, name)
|
86
82
|
end
|
87
83
|
|
88
84
|
def self.define_callbacks(model, reflection)
|
@@ -133,8 +129,6 @@ module ActiveRecord::Associations::Builder
|
|
133
129
|
raise NotImplementedError
|
134
130
|
end
|
135
131
|
|
136
|
-
private
|
137
|
-
|
138
132
|
def self.check_dependent_options(dependent)
|
139
133
|
unless valid_dependent_options.include? dependent
|
140
134
|
raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{dependent}"
|
@@ -1,11 +1,11 @@
|
|
1
|
-
module ActiveRecord::Associations::Builder
|
1
|
+
module ActiveRecord::Associations::Builder # :nodoc:
|
2
2
|
class BelongsTo < SingularAssociation #:nodoc:
|
3
|
-
def macro
|
3
|
+
def self.macro
|
4
4
|
:belongs_to
|
5
5
|
end
|
6
6
|
|
7
|
-
def valid_options
|
8
|
-
super + [:
|
7
|
+
def self.valid_options(options)
|
8
|
+
super + [:polymorphic, :touch, :counter_cache, :optional]
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.valid_dependent_options
|
@@ -23,8 +23,6 @@ module ActiveRecord::Associations::Builder
|
|
23
23
|
add_counter_cache_methods mixin
|
24
24
|
end
|
25
25
|
|
26
|
-
private
|
27
|
-
|
28
26
|
def self.add_counter_cache_methods(mixin)
|
29
27
|
return if mixin.method_defined? :belongs_to_counter_cache_after_update
|
30
28
|
|
@@ -35,16 +33,26 @@ module ActiveRecord::Associations::Builder
|
|
35
33
|
|
36
34
|
if (@_after_create_counter_called ||= false)
|
37
35
|
@_after_create_counter_called = false
|
38
|
-
elsif
|
39
|
-
|
36
|
+
elsif (@_after_replace_counter_called ||= false)
|
37
|
+
@_after_replace_counter_called = false
|
38
|
+
elsif attribute_changed?(foreign_key) && !new_record?
|
39
|
+
if reflection.polymorphic?
|
40
|
+
model = attribute(reflection.foreign_type).try(:constantize)
|
41
|
+
model_was = attribute_was(reflection.foreign_type).try(:constantize)
|
42
|
+
else
|
43
|
+
model = reflection.klass
|
44
|
+
model_was = reflection.klass
|
45
|
+
end
|
46
|
+
|
40
47
|
foreign_key_was = attribute_was foreign_key
|
41
48
|
foreign_key = attribute foreign_key
|
42
49
|
|
43
50
|
if foreign_key && model.respond_to?(:increment_counter)
|
44
51
|
model.increment_counter(cache_column, foreign_key)
|
45
52
|
end
|
46
|
-
|
47
|
-
|
53
|
+
|
54
|
+
if foreign_key_was && model_was.respond_to?(:decrement_counter)
|
55
|
+
model_was.decrement_counter(cache_column, foreign_key_was)
|
48
56
|
end
|
49
57
|
end
|
50
58
|
end
|
@@ -62,7 +70,7 @@ module ActiveRecord::Associations::Builder
|
|
62
70
|
klass.attr_readonly cache_column if klass && klass.respond_to?(:attr_readonly)
|
63
71
|
end
|
64
72
|
|
65
|
-
def self.touch_record(o, foreign_key, name, touch) # :nodoc:
|
73
|
+
def self.touch_record(o, foreign_key, name, touch, touch_method) # :nodoc:
|
66
74
|
old_foreign_id = o.changed_attributes[foreign_key]
|
67
75
|
|
68
76
|
if old_foreign_id
|
@@ -77,9 +85,9 @@ module ActiveRecord::Associations::Builder
|
|
77
85
|
|
78
86
|
if old_record
|
79
87
|
if touch != true
|
80
|
-
old_record.
|
88
|
+
old_record.send(touch_method, touch)
|
81
89
|
else
|
82
|
-
old_record.
|
90
|
+
old_record.send(touch_method)
|
83
91
|
end
|
84
92
|
end
|
85
93
|
end
|
@@ -87,9 +95,9 @@ module ActiveRecord::Associations::Builder
|
|
87
95
|
record = o.send name
|
88
96
|
if record && record.persisted?
|
89
97
|
if touch != true
|
90
|
-
record.
|
98
|
+
record.send(touch_method, touch)
|
91
99
|
else
|
92
|
-
record.
|
100
|
+
record.send(touch_method)
|
93
101
|
end
|
94
102
|
end
|
95
103
|
end
|
@@ -100,7 +108,7 @@ module ActiveRecord::Associations::Builder
|
|
100
108
|
touch = reflection.options[:touch]
|
101
109
|
|
102
110
|
callback = lambda { |record|
|
103
|
-
BelongsTo.touch_record(record, foreign_key, n, touch)
|
111
|
+
BelongsTo.touch_record(record, foreign_key, n, touch, belongs_to_touch_method)
|
104
112
|
}
|
105
113
|
|
106
114
|
model.after_save callback, if: :changed?
|
@@ -109,8 +117,25 @@ module ActiveRecord::Associations::Builder
|
|
109
117
|
end
|
110
118
|
|
111
119
|
def self.add_destroy_callbacks(model, reflection)
|
112
|
-
|
113
|
-
|
120
|
+
model.after_destroy lambda { |o| o.association(reflection.name).handle_dependency }
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.define_validations(model, reflection)
|
124
|
+
if reflection.options.key?(:required)
|
125
|
+
reflection.options[:optional] = !reflection.options.delete(:required)
|
126
|
+
end
|
127
|
+
|
128
|
+
if reflection.options[:optional].nil?
|
129
|
+
required = model.belongs_to_required_by_default
|
130
|
+
else
|
131
|
+
required = !reflection.options[:optional]
|
132
|
+
end
|
133
|
+
|
134
|
+
super
|
135
|
+
|
136
|
+
if required
|
137
|
+
model.validates_presence_of reflection.name, message: :required
|
138
|
+
end
|
114
139
|
end
|
115
140
|
end
|
116
141
|
end
|
@@ -2,27 +2,16 @@
|
|
2
2
|
|
3
3
|
require 'active_record/associations'
|
4
4
|
|
5
|
-
module ActiveRecord::Associations::Builder
|
5
|
+
module ActiveRecord::Associations::Builder # :nodoc:
|
6
6
|
class CollectionAssociation < Association #:nodoc:
|
7
7
|
|
8
8
|
CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
|
9
9
|
|
10
|
-
def valid_options
|
10
|
+
def self.valid_options(options)
|
11
11
|
super + [:table_name, :before_add,
|
12
12
|
:after_add, :before_remove, :after_remove, :extend]
|
13
13
|
end
|
14
14
|
|
15
|
-
attr_reader :block_extension
|
16
|
-
|
17
|
-
def initialize(model, name, scope, options)
|
18
|
-
super
|
19
|
-
@mod = nil
|
20
|
-
if block_given?
|
21
|
-
@mod = Module.new(&Proc.new)
|
22
|
-
@scope = wrap_scope @scope, @mod
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
15
|
def self.define_callbacks(model, reflection)
|
27
16
|
super
|
28
17
|
name = reflection.name
|
@@ -32,10 +21,11 @@ module ActiveRecord::Associations::Builder
|
|
32
21
|
}
|
33
22
|
end
|
34
23
|
|
35
|
-
def define_extensions(model)
|
36
|
-
if
|
24
|
+
def self.define_extensions(model, name)
|
25
|
+
if block_given?
|
37
26
|
extension_module_name = "#{model.name.demodulize}#{name.to_s.camelize}AssociationExtension"
|
38
|
-
|
27
|
+
extension = Module.new(&Proc.new)
|
28
|
+
model.parent.const_set(extension_module_name, extension)
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
@@ -78,9 +68,7 @@ module ActiveRecord::Associations::Builder
|
|
78
68
|
CODE
|
79
69
|
end
|
80
70
|
|
81
|
-
|
82
|
-
|
83
|
-
def wrap_scope(scope, mod)
|
71
|
+
def self.wrap_scope(scope, mod)
|
84
72
|
if scope
|
85
73
|
if scope.arity > 0
|
86
74
|
proc { |owner| instance_exec(owner, &scope).extending(mod) }
|
@@ -1,9 +1,9 @@
|
|
1
|
-
module ActiveRecord::Associations::Builder
|
1
|
+
module ActiveRecord::Associations::Builder # :nodoc:
|
2
2
|
class HasAndBelongsToMany # :nodoc:
|
3
|
-
class JoinTableResolver
|
3
|
+
class JoinTableResolver # :nodoc:
|
4
4
|
KnownTable = Struct.new :join_table
|
5
5
|
|
6
|
-
class KnownClass
|
6
|
+
class KnownClass # :nodoc:
|
7
7
|
def initialize(lhs_class, rhs_class_name)
|
8
8
|
@lhs_class = lhs_class
|
9
9
|
@rhs_class_name = rhs_class_name
|
@@ -62,13 +62,13 @@ module ActiveRecord::Associations::Builder
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def self.add_left_association(name, options)
|
65
|
-
belongs_to name, options
|
65
|
+
belongs_to name, required: false, **options
|
66
66
|
self.left_reflection = _reflect_on_association(name)
|
67
67
|
end
|
68
68
|
|
69
69
|
def self.add_right_association(name, options)
|
70
70
|
rhs_name = name.to_s.singularize.to_sym
|
71
|
-
belongs_to rhs_name, options
|
71
|
+
belongs_to rhs_name, required: false, **options
|
72
72
|
self.right_reflection = _reflect_on_association(rhs_name)
|
73
73
|
end
|
74
74
|
|
@@ -76,6 +76,9 @@ module ActiveRecord::Associations::Builder
|
|
76
76
|
left_model.retrieve_connection
|
77
77
|
end
|
78
78
|
|
79
|
+
def self.primary_key
|
80
|
+
false
|
81
|
+
end
|
79
82
|
}
|
80
83
|
|
81
84
|
join_model.name = "HABTM_#{association_name.to_s.camelize}"
|
@@ -89,13 +92,13 @@ module ActiveRecord::Associations::Builder
|
|
89
92
|
|
90
93
|
def middle_reflection(join_model)
|
91
94
|
middle_name = [lhs_model.name.downcase.pluralize,
|
92
|
-
association_name].join('_').gsub(
|
95
|
+
association_name].join('_'.freeze).gsub('::'.freeze, '_'.freeze).to_sym
|
93
96
|
middle_options = middle_options join_model
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
|
98
|
+
HasMany.create_reflection(lhs_model,
|
99
|
+
middle_name,
|
100
|
+
nil,
|
101
|
+
middle_options)
|
99
102
|
end
|
100
103
|
|
101
104
|
private
|
@@ -1,11 +1,11 @@
|
|
1
|
-
module ActiveRecord::Associations::Builder
|
1
|
+
module ActiveRecord::Associations::Builder # :nodoc:
|
2
2
|
class HasMany < CollectionAssociation #:nodoc:
|
3
|
-
def macro
|
3
|
+
def self.macro
|
4
4
|
:has_many
|
5
5
|
end
|
6
6
|
|
7
|
-
def valid_options
|
8
|
-
super + [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache, :join_table, :foreign_type]
|
7
|
+
def self.valid_options(options)
|
8
|
+
super + [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache, :join_table, :foreign_type, :index_errors]
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.valid_dependent_options
|
@@ -1,11 +1,11 @@
|
|
1
|
-
module ActiveRecord::Associations::Builder
|
1
|
+
module ActiveRecord::Associations::Builder # :nodoc:
|
2
2
|
class HasOne < SingularAssociation #:nodoc:
|
3
|
-
def macro
|
3
|
+
def self.macro
|
4
4
|
:has_one
|
5
5
|
end
|
6
6
|
|
7
|
-
def valid_options
|
8
|
-
valid = super + [:as
|
7
|
+
def self.valid_options(options)
|
8
|
+
valid = super + [:as]
|
9
9
|
valid += [:through, :source, :source_type] if options[:through]
|
10
10
|
valid
|
11
11
|
end
|
@@ -14,10 +14,15 @@ module ActiveRecord::Associations::Builder
|
|
14
14
|
[:destroy, :delete, :nullify, :restrict_with_error, :restrict_with_exception]
|
15
15
|
end
|
16
16
|
|
17
|
-
private
|
18
|
-
|
19
17
|
def self.add_destroy_callbacks(model, reflection)
|
20
18
|
super unless reflection.options[:through]
|
21
19
|
end
|
20
|
+
|
21
|
+
def self.define_validations(model, reflection)
|
22
|
+
super
|
23
|
+
if reflection.options[:required]
|
24
|
+
model.validates_presence_of reflection.name, message: :required
|
25
|
+
end
|
26
|
+
end
|
22
27
|
end
|
23
28
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# This class is inherited by the has_one and belongs_to association classes
|
2
2
|
|
3
|
-
module ActiveRecord::Associations::Builder
|
3
|
+
module ActiveRecord::Associations::Builder # :nodoc:
|
4
4
|
class SingularAssociation < Association #:nodoc:
|
5
|
-
def valid_options
|
6
|
-
super + [:dependent, :primary_key, :inverse_of, :required]
|
5
|
+
def self.valid_options(options)
|
6
|
+
super + [:foreign_type, :dependent, :primary_key, :inverse_of, :required]
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.define_accessors(model, reflection)
|
@@ -27,12 +27,5 @@ module ActiveRecord::Associations::Builder
|
|
27
27
|
end
|
28
28
|
CODE
|
29
29
|
end
|
30
|
-
|
31
|
-
def self.define_validations(model, reflection)
|
32
|
-
super
|
33
|
-
if reflection.options[:required]
|
34
|
-
model.validates_presence_of reflection.name
|
35
|
-
end
|
36
|
-
end
|
37
30
|
end
|
38
31
|
end
|