activerecord 3.2.22.5 → 4.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1024 -543
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -29
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +55 -44
- data/lib/active_record/aggregations.rb +40 -34
- data/lib/active_record/associations.rb +204 -276
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +30 -35
- data/lib/active_record/associations/association_scope.rb +40 -40
- data/lib/active_record/associations/belongs_to_association.rb +15 -2
- data/lib/active_record/associations/builder/association.rb +81 -28
- data/lib/active_record/associations/builder/belongs_to.rb +35 -57
- data/lib/active_record/associations/builder/collection_association.rb +54 -40
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -64
- data/lib/active_record/associations/builder/has_one.rb +13 -50
- data/lib/active_record/associations/builder/singular_association.rb +13 -13
- data/lib/active_record/associations/collection_association.rb +92 -88
- data/lib/active_record/associations/collection_proxy.rb +913 -63
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -10
- data/lib/active_record/associations/has_many_association.rb +35 -9
- data/lib/active_record/associations/has_many_through_association.rb +24 -14
- data/lib/active_record/associations/has_one_association.rb +33 -13
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_helper.rb +1 -11
- data/lib/active_record/associations/preloader.rb +14 -17
- data/lib/active_record/associations/preloader/association.rb +29 -33
- data/lib/active_record/associations/preloader/collection_association.rb +1 -1
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +1 -1
- data/lib/active_record/associations/preloader/through_association.rb +13 -17
- data/lib/active_record/associations/singular_association.rb +11 -11
- data/lib/active_record/associations/through_association.rb +2 -2
- data/lib/active_record/attribute_assignment.rb +133 -153
- data/lib/active_record/attribute_methods.rb +196 -93
- data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
- data/lib/active_record/attribute_methods/dirty.rb +31 -28
- data/lib/active_record/attribute_methods/primary_key.rb +38 -30
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +62 -91
- data/lib/active_record/attribute_methods/serialization.rb +97 -66
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -45
- data/lib/active_record/attribute_methods/write.rb +32 -39
- data/lib/active_record/autosave_association.rb +56 -70
- data/lib/active_record/base.rb +53 -450
- data/lib/active_record/callbacks.rb +53 -18
- data/lib/active_record/coders/yaml_column.rb +11 -9
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +353 -197
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -131
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -3
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +101 -91
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +225 -96
- data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +99 -46
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +114 -36
- data/lib/active_record/connection_adapters/column.rb +46 -24
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
- data/lib/active_record/connection_adapters/mysql_adapter.rb +181 -64
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +132 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +347 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +158 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +448 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +454 -885
- data/lib/active_record/connection_adapters/schema_cache.rb +48 -16
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +574 -13
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +428 -0
- data/lib/active_record/counter_cache.rb +106 -108
- data/lib/active_record/dynamic_matchers.rb +110 -63
- data/lib/active_record/errors.rb +25 -8
- data/lib/active_record/explain.rb +8 -58
- data/lib/active_record/explain_subscriber.rb +6 -3
- data/lib/active_record/fixture_set/file.rb +56 -0
- data/lib/active_record/fixtures.rb +146 -148
- data/lib/active_record/inheritance.rb +77 -59
- data/lib/active_record/integration.rb +5 -5
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +38 -42
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +19 -9
- data/lib/active_record/migration.rb +318 -153
- data/lib/active_record/migration/command_recorder.rb +90 -31
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/model_schema.rb +69 -92
- data/lib/active_record/nested_attributes.rb +113 -148
- data/lib/active_record/null_relation.rb +65 -0
- data/lib/active_record/persistence.rb +188 -97
- data/lib/active_record/query_cache.rb +18 -36
- data/lib/active_record/querying.rb +19 -15
- data/lib/active_record/railtie.rb +91 -36
- data/lib/active_record/railties/console_sandbox.rb +0 -2
- data/lib/active_record/railties/controller_runtime.rb +2 -2
- data/lib/active_record/railties/databases.rake +90 -309
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +7 -3
- data/lib/active_record/reflection.rb +72 -56
- data/lib/active_record/relation.rb +241 -157
- data/lib/active_record/relation/batches.rb +25 -22
- data/lib/active_record/relation/calculations.rb +143 -121
- data/lib/active_record/relation/delegation.rb +96 -18
- data/lib/active_record/relation/finder_methods.rb +117 -183
- data/lib/active_record/relation/merger.rb +133 -0
- data/lib/active_record/relation/predicate_builder.rb +90 -42
- data/lib/active_record/relation/query_methods.rb +666 -136
- data/lib/active_record/relation/spawn_methods.rb +43 -150
- data/lib/active_record/result.rb +33 -6
- data/lib/active_record/sanitization.rb +24 -50
- data/lib/active_record/schema.rb +19 -12
- data/lib/active_record/schema_dumper.rb +31 -39
- data/lib/active_record/schema_migration.rb +36 -0
- data/lib/active_record/scoping.rb +0 -124
- data/lib/active_record/scoping/default.rb +48 -45
- data/lib/active_record/scoping/named.rb +74 -103
- data/lib/active_record/serialization.rb +6 -2
- data/lib/active_record/serializers/xml_serializer.rb +9 -15
- data/lib/active_record/store.rb +119 -15
- data/lib/active_record/tasks/database_tasks.rb +158 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +138 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/test_case.rb +61 -38
- data/lib/active_record/timestamp.rb +8 -9
- data/lib/active_record/transactions.rb +65 -51
- data/lib/active_record/validations.rb +17 -15
- data/lib/active_record/validations/associated.rb +20 -14
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +93 -52
- data/lib/active_record/version.rb +4 -4
- data/lib/rails/generators/active_record.rb +3 -5
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -7
- data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
- data/lib/rails/generators/active_record/model/model_generator.rb +4 -3
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -6
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- metadata +53 -46
- 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/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/session_store.rb +0 -360
- data/lib/rails/generators/active_record/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
@@ -1,10 +1,12 @@
|
|
1
|
-
require 'active_support/core_ext/object/inclusion'
|
2
|
-
|
3
1
|
module ActiveRecord::Associations::Builder
|
4
2
|
class BelongsTo < SingularAssociation #:nodoc:
|
5
|
-
|
3
|
+
def macro
|
4
|
+
:belongs_to
|
5
|
+
end
|
6
6
|
|
7
|
-
|
7
|
+
def valid_options
|
8
|
+
super + [:foreign_type, :polymorphic, :touch]
|
9
|
+
end
|
8
10
|
|
9
11
|
def constructable?
|
10
12
|
!options[:polymorphic]
|
@@ -14,75 +16,51 @@ module ActiveRecord::Associations::Builder
|
|
14
16
|
reflection = super
|
15
17
|
add_counter_cache_callbacks(reflection) if options[:counter_cache]
|
16
18
|
add_touch_callbacks(reflection) if options[:touch]
|
17
|
-
configure_dependency
|
18
19
|
reflection
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
+
def add_counter_cache_callbacks(reflection)
|
23
|
+
cache_column = reflection.counter_cache_column
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
method_name = "belongs_to_counter_cache_after_create_for_#{name}"
|
28
|
-
mixin.redefine_method(method_name) do
|
29
|
-
record = send(name)
|
30
|
-
record.class.increment_counter(cache_column, record.id) unless record.nil?
|
25
|
+
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
26
|
+
def belongs_to_counter_cache_after_create_for_#{name}
|
27
|
+
record = #{name}
|
28
|
+
record.class.increment_counter(:#{cache_column}, record.id) unless record.nil?
|
31
29
|
end
|
32
|
-
model.after_create(method_name)
|
33
|
-
|
34
|
-
method_name = "belongs_to_counter_cache_before_destroy_for_#{name}"
|
35
|
-
mixin.redefine_method(method_name) do
|
36
|
-
record = send(name)
|
37
30
|
|
38
|
-
|
39
|
-
|
31
|
+
def belongs_to_counter_cache_before_destroy_for_#{name}
|
32
|
+
unless marked_for_destruction?
|
33
|
+
record = #{name}
|
34
|
+
record.class.decrement_counter(:#{cache_column}, record.id) unless record.nil?
|
40
35
|
end
|
41
36
|
end
|
42
|
-
|
37
|
+
CODE
|
43
38
|
|
44
|
-
|
45
|
-
|
46
|
-
)
|
47
|
-
end
|
39
|
+
model.after_create "belongs_to_counter_cache_after_create_for_#{name}"
|
40
|
+
model.before_destroy "belongs_to_counter_cache_before_destroy_for_#{name}"
|
48
41
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
touch = options[:touch]
|
42
|
+
klass = reflection.class_name.safe_constantize
|
43
|
+
klass.attr_readonly cache_column if klass && klass.respond_to?(:attr_readonly)
|
44
|
+
end
|
53
45
|
|
54
|
-
|
55
|
-
|
46
|
+
def add_touch_callbacks(reflection)
|
47
|
+
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
48
|
+
def belongs_to_touch_after_save_or_destroy_for_#{name}
|
49
|
+
record = #{name}
|
56
50
|
|
57
51
|
unless record.nil?
|
58
|
-
if touch
|
59
|
-
record.touch
|
60
|
-
else
|
61
|
-
record.touch(touch)
|
62
|
-
end
|
52
|
+
record.touch #{options[:touch].inspect if options[:touch] != true}
|
63
53
|
end
|
64
54
|
end
|
55
|
+
CODE
|
65
56
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
def configure_dependency
|
72
|
-
if options[:dependent]
|
73
|
-
unless options[:dependent].in?([:destroy, :delete])
|
74
|
-
raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{options[:dependent].inspect})"
|
75
|
-
end
|
57
|
+
model.after_save "belongs_to_touch_after_save_or_destroy_for_#{name}"
|
58
|
+
model.after_touch "belongs_to_touch_after_save_or_destroy_for_#{name}"
|
59
|
+
model.after_destroy "belongs_to_touch_after_save_or_destroy_for_#{name}"
|
60
|
+
end
|
76
61
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
association = #{name}
|
81
|
-
association.#{options[:dependent]} if association
|
82
|
-
end
|
83
|
-
eoruby
|
84
|
-
model.after_destroy method_name
|
85
|
-
end
|
86
|
-
end
|
62
|
+
def valid_dependent_options
|
63
|
+
[:destroy, :delete]
|
64
|
+
end
|
87
65
|
end
|
88
66
|
end
|
@@ -1,24 +1,24 @@
|
|
1
|
+
require 'active_record/associations'
|
2
|
+
|
1
3
|
module ActiveRecord::Associations::Builder
|
2
4
|
class CollectionAssociation < Association #:nodoc:
|
3
|
-
CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
|
4
|
-
|
5
|
-
self.valid_options += [
|
6
|
-
:table_name, :order, :group, :having, :limit, :offset, :uniq, :finder_sql,
|
7
|
-
:counter_sql, :before_add, :after_add, :before_remove, :after_remove
|
8
|
-
]
|
9
5
|
|
10
|
-
|
6
|
+
CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
|
11
7
|
|
12
|
-
def
|
13
|
-
|
8
|
+
def valid_options
|
9
|
+
super + [:table_name, :finder_sql, :counter_sql, :before_add,
|
10
|
+
:after_add, :before_remove, :after_remove, :extend]
|
14
11
|
end
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
attr_reader :block_extension, :extension_module
|
14
|
+
|
15
|
+
def initialize(*args, &extension)
|
16
|
+
super(*args)
|
18
17
|
@block_extension = extension
|
19
18
|
end
|
20
19
|
|
21
20
|
def build
|
21
|
+
show_deprecation_warnings
|
22
22
|
wrap_block_extension
|
23
23
|
reflection = super
|
24
24
|
CALLBACKS.each { |callback_name| define_callback(callback_name) }
|
@@ -29,47 +29,61 @@ module ActiveRecord::Associations::Builder
|
|
29
29
|
true
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
def show_deprecation_warnings
|
33
|
+
[:finder_sql, :counter_sql].each do |name|
|
34
|
+
if options.include? name
|
35
|
+
ActiveSupport::Deprecation.warn("The :#{name} association option is deprecated. Please find an alternative (such as using scopes).")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def wrap_block_extension
|
41
|
+
if block_extension
|
42
|
+
@extension_module = mod = Module.new(&block_extension)
|
43
|
+
silence_warnings do
|
44
|
+
model.parent.const_set(extension_module_name, mod)
|
45
|
+
end
|
33
46
|
|
34
|
-
|
35
|
-
options[:extend] = Array.wrap(options[:extend])
|
47
|
+
prev_scope = @scope
|
36
48
|
|
37
|
-
if
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
options[:extend].push("#{model.parent}::#{extension_module_name}".constantize)
|
49
|
+
if prev_scope
|
50
|
+
@scope = proc { |owner| instance_exec(owner, &prev_scope).extending(mod) }
|
51
|
+
else
|
52
|
+
@scope = proc { extending(mod) }
|
42
53
|
end
|
43
54
|
end
|
55
|
+
end
|
44
56
|
|
45
|
-
|
46
|
-
|
47
|
-
|
57
|
+
def extension_module_name
|
58
|
+
@extension_module_name ||= "#{model.name.demodulize}#{name.to_s.camelize}AssociationExtension"
|
59
|
+
end
|
48
60
|
|
49
|
-
|
50
|
-
|
61
|
+
def define_callback(callback_name)
|
62
|
+
full_callback_name = "#{callback_name}_for_#{name}"
|
51
63
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
64
|
+
# TODO : why do i need method_defined? I think its because of the inheritance chain
|
65
|
+
model.class_attribute full_callback_name.to_sym unless model.method_defined?(full_callback_name)
|
66
|
+
model.send("#{full_callback_name}=", Array(options[callback_name.to_sym]))
|
67
|
+
end
|
56
68
|
|
57
|
-
|
58
|
-
|
69
|
+
def define_readers
|
70
|
+
super
|
59
71
|
|
60
|
-
|
61
|
-
|
62
|
-
association(name).ids_reader
|
72
|
+
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
73
|
+
def #{name.to_s.singularize}_ids
|
74
|
+
association(:#{name}).ids_reader
|
63
75
|
end
|
64
|
-
|
76
|
+
CODE
|
77
|
+
end
|
65
78
|
|
66
|
-
|
67
|
-
|
79
|
+
def define_writers
|
80
|
+
super
|
68
81
|
|
69
|
-
|
70
|
-
|
71
|
-
association(name).ids_writer(ids)
|
82
|
+
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
83
|
+
def #{name.to_s.singularize}_ids=(ids)
|
84
|
+
association(:#{name}).ids_writer(ids)
|
72
85
|
end
|
73
|
-
|
86
|
+
CODE
|
87
|
+
end
|
74
88
|
end
|
75
89
|
end
|
@@ -1,57 +1,39 @@
|
|
1
1
|
module ActiveRecord::Associations::Builder
|
2
2
|
class HasAndBelongsToMany < CollectionAssociation #:nodoc:
|
3
|
-
|
3
|
+
def macro
|
4
|
+
:has_and_belongs_to_many
|
5
|
+
end
|
4
6
|
|
5
|
-
|
7
|
+
def valid_options
|
8
|
+
super + [:join_table, :association_foreign_key, :delete_sql, :insert_sql]
|
9
|
+
end
|
6
10
|
|
7
11
|
def build
|
8
12
|
reflection = super
|
9
|
-
check_validity(reflection)
|
10
13
|
define_destroy_hook
|
11
14
|
reflection
|
12
15
|
end
|
13
16
|
|
14
|
-
|
17
|
+
def show_deprecation_warnings
|
18
|
+
super
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
20
|
-
def destroy_associations
|
21
|
-
association(#{name.to_sym.inspect}).delete_all_on_destroy
|
22
|
-
super
|
23
|
-
end
|
24
|
-
RUBY
|
25
|
-
})
|
26
|
-
end
|
27
|
-
|
28
|
-
# TODO: These checks should probably be moved into the Reflection, and we should not be
|
29
|
-
# redefining the options[:join_table] value - instead we should define a
|
30
|
-
# reflection.join_table method.
|
31
|
-
def check_validity(reflection)
|
32
|
-
if reflection.association_foreign_key == reflection.foreign_key
|
33
|
-
raise ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded.new(reflection)
|
20
|
+
[:delete_sql, :insert_sql].each do |name|
|
21
|
+
if options.include? name
|
22
|
+
ActiveSupport::Deprecation.warn("The :#{name} association option is deprecated. Please find an alternative (such as using has_many :through).")
|
34
23
|
end
|
35
|
-
|
36
|
-
reflection.options[:join_table] ||= join_table_name(
|
37
|
-
model.send(:undecorated_table_name, model.to_s),
|
38
|
-
model.send(:undecorated_table_name, reflection.class_name)
|
39
|
-
)
|
40
24
|
end
|
25
|
+
end
|
41
26
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
model.table_name_prefix + join_table + model.table_name_suffix
|
55
|
-
end
|
27
|
+
def define_destroy_hook
|
28
|
+
name = self.name
|
29
|
+
model.send(:include, Module.new {
|
30
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
31
|
+
def destroy_associations
|
32
|
+
association(:#{name}).delete_all
|
33
|
+
super
|
34
|
+
end
|
35
|
+
RUBY
|
36
|
+
})
|
37
|
+
end
|
56
38
|
end
|
57
39
|
end
|
@@ -1,71 +1,15 @@
|
|
1
|
-
require 'active_support/core_ext/object/inclusion'
|
2
|
-
|
3
1
|
module ActiveRecord::Associations::Builder
|
4
2
|
class HasMany < CollectionAssociation #:nodoc:
|
5
|
-
|
6
|
-
|
7
|
-
self.valid_options += [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of]
|
8
|
-
|
9
|
-
def build
|
10
|
-
reflection = super
|
11
|
-
configure_dependency
|
12
|
-
reflection
|
3
|
+
def macro
|
4
|
+
:has_many
|
13
5
|
end
|
14
6
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if options[:dependent]
|
19
|
-
unless options[:dependent].in?([:destroy, :delete_all, :nullify, :restrict])
|
20
|
-
raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, " \
|
21
|
-
":nullify or :restrict (#{options[:dependent].inspect})"
|
22
|
-
end
|
23
|
-
|
24
|
-
send("define_#{options[:dependent]}_dependency_method")
|
25
|
-
model.before_destroy dependency_method_name
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def define_destroy_dependency_method
|
30
|
-
name = self.name
|
31
|
-
mixin.redefine_method(dependency_method_name) do
|
32
|
-
send(name).each do |o|
|
33
|
-
# No point in executing the counter update since we're going to destroy the parent anyway
|
34
|
-
counter_method = ('belongs_to_counter_cache_before_destroy_for_' + self.class.name.downcase).to_sym
|
35
|
-
if o.respond_to?(counter_method)
|
36
|
-
class << o
|
37
|
-
self
|
38
|
-
end.send(:define_method, counter_method, Proc.new {})
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
send(name).delete_all
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def define_delete_all_dependency_method
|
47
|
-
name = self.name
|
48
|
-
mixin.redefine_method(dependency_method_name) do
|
49
|
-
association(name).delete_all_on_destroy
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def define_nullify_dependency_method
|
54
|
-
name = self.name
|
55
|
-
mixin.redefine_method(dependency_method_name) do
|
56
|
-
send(name).delete_all
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def define_restrict_dependency_method
|
61
|
-
name = self.name
|
62
|
-
mixin.redefine_method(dependency_method_name) do
|
63
|
-
raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).empty?
|
64
|
-
end
|
65
|
-
end
|
7
|
+
def valid_options
|
8
|
+
super + [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache]
|
9
|
+
end
|
66
10
|
|
67
|
-
|
68
|
-
|
69
|
-
|
11
|
+
def valid_dependent_options
|
12
|
+
[:destroy, :delete_all, :nullify, :restrict, :restrict_with_error, :restrict_with_exception]
|
13
|
+
end
|
70
14
|
end
|
71
15
|
end
|
@@ -1,62 +1,25 @@
|
|
1
|
-
require 'active_support/core_ext/object/inclusion'
|
2
|
-
|
3
1
|
module ActiveRecord::Associations::Builder
|
4
2
|
class HasOne < SingularAssociation #:nodoc:
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
def macro
|
4
|
+
:has_one
|
5
|
+
end
|
8
6
|
|
9
|
-
|
10
|
-
|
7
|
+
def valid_options
|
8
|
+
valid = super + [:order, :as]
|
9
|
+
valid += [:through, :source, :source_type] if options[:through]
|
10
|
+
valid
|
11
|
+
end
|
11
12
|
|
12
13
|
def constructable?
|
13
14
|
!options[:through]
|
14
15
|
end
|
15
16
|
|
16
|
-
def
|
17
|
-
|
18
|
-
configure_dependency unless options[:through]
|
19
|
-
reflection
|
17
|
+
def configure_dependency
|
18
|
+
super unless options[:through]
|
20
19
|
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
valid_options = self.class.valid_options
|
26
|
-
valid_options += self.class.through_options if options[:through]
|
27
|
-
options.assert_valid_keys(valid_options)
|
28
|
-
end
|
29
|
-
|
30
|
-
def configure_dependency
|
31
|
-
if options[:dependent]
|
32
|
-
unless options[:dependent].in?([:destroy, :delete, :nullify, :restrict])
|
33
|
-
raise ArgumentError, "The :dependent option expects either :destroy, :delete, " \
|
34
|
-
":nullify or :restrict (#{options[:dependent].inspect})"
|
35
|
-
end
|
36
|
-
|
37
|
-
send("define_#{options[:dependent]}_dependency_method")
|
38
|
-
model.before_destroy dependency_method_name
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def dependency_method_name
|
43
|
-
"has_one_dependent_#{options[:dependent]}_for_#{name}"
|
44
|
-
end
|
45
|
-
|
46
|
-
def define_destroy_dependency_method
|
47
|
-
name = self.name
|
48
|
-
mixin.redefine_method(dependency_method_name) do
|
49
|
-
association(name).delete
|
50
|
-
end
|
51
|
-
end
|
52
|
-
alias :define_delete_dependency_method :define_destroy_dependency_method
|
53
|
-
alias :define_nullify_dependency_method :define_destroy_dependency_method
|
54
|
-
|
55
|
-
def define_restrict_dependency_method
|
56
|
-
name = self.name
|
57
|
-
mixin.redefine_method(dependency_method_name) do
|
58
|
-
raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).nil?
|
59
|
-
end
|
60
|
-
end
|
21
|
+
def valid_dependent_options
|
22
|
+
[:destroy, :delete, :nullify, :restrict, :restrict_with_error, :restrict_with_exception]
|
23
|
+
end
|
61
24
|
end
|
62
25
|
end
|