1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
module ActiveRecord::Associations::Builder
class Association #:nodoc:
class << self
attr_accessor :valid_options
end
self.valid_options = [:class_name, :foreign_key, :validate]
attr_reader :model, :name, :scope, :options, :reflection
def self.build(*args, &block)
new(*args, &block).build
end
def initialize(model, name, scope, options)
@model = model
@name = name
if scope.is_a?(Hash)
@scope = nil
@options = scope
else
@scope = scope
@options = options
end
if @scope && @scope.arity == 0
prev_scope = @scope
@scope = proc { instance_exec(&prev_scope) }
end
end
def mixin
@model.generated_feature_methods
end
include Module.new { def build; end }
def build
validate_options
define_accessors
@reflection = model.create_reflection(macro, name, scope, options, model)
super # provides an extension point
@reflection
end
def macro
raise NotImplementedError
end
def valid_options
Association.valid_options
end
private
def validate_options
options.assert_valid_keys(valid_options)
end
def define_accessors
define_readers
define_writers
end
def define_readers
name = self.name
mixin.redefine_method(name) do |*params|
association(name).reader(*params)
end
end
def define_writers
name = self.name
mixin.redefine_method("#{name}=") do |value|
association(name).writer(value)
end
end
def dependent_restrict_raises?
ActiveRecord::Base.dependent_restrict_raises == true
end
def dependent_restrict_deprecation_warning
if dependent_restrict_raises?
msg = "In the next release, `:dependent => :restrict` will not raise a `DeleteRestrictionError`. "\
"Instead, it will add an error on the model. To fix this warning, make sure your code " \
"isn't relying on a `DeleteRestrictionError` and then add " \
"`config.active_record.dependent_restrict_raises = false` to your application config."
ActiveSupport::Deprecation.warn msg
end
end
def define_restrict_dependency_method
name = self.name
mixin.redefine_method(dependency_method_name) do
has_one_macro = association(name).reflection.macro == :has_one
if has_one_macro ? !send(name).nil? : send(name).exists?
if dependent_restrict_raises?
raise ActiveRecord::DeleteRestrictionError.new(name)
else
key = has_one_macro ? "one" : "many"
errors.add(:base, :"restrict_dependent_destroy.#{key}",
:record => self.class.human_attribute_name(name).downcase)
return false
end
end
end
end
end
end
|