aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorGeorge Claghorn <george.claghorn@gmail.com>2017-03-17 10:29:19 -0400
committerDavid Heinemeier Hansson <david@loudthinking.com>2017-03-17 15:29:19 +0100
commit73b86ac58b61b4c7b888962252a1a86dffb24081 (patch)
treeea34e055f17867f3811a874bdc51461b40fc417f /activerecord/lib
parenteadbc82c47fd157ed4f1eb4c4983ab0734023106 (diff)
downloadrails-73b86ac58b61b4c7b888962252a1a86dffb24081.tar.gz
rails-73b86ac58b61b4c7b888962252a1a86dffb24081.tar.bz2
rails-73b86ac58b61b4c7b888962252a1a86dffb24081.zip
Add :default option to belongs_to (#28453)
Use it to specify that an association should be initialized with a particular record before validation. For example: # Before belongs_to :account before_validation -> { self.account ||= Current.account } # After belongs_to :account, default: -> { Current.account }
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/associations.rb4
-rw-r--r--activerecord/lib/active_record/associations/belongs_to_association.rb4
-rw-r--r--activerecord/lib/active_record/associations/builder/belongs_to.rb9
3 files changed, 16 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 4606c91ffd..6efa448d49 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1647,6 +1647,9 @@ module ActiveRecord
# +:inverse_of+ to avoid an extra query during validation.
# NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
# you don't want to have association presence validated, use <tt>optional: true</tt>.
+ # [:default]
+ # Provide a callable (i.e. proc or lambda) to specify that the association should
+ # be initialized with a particular record before validation.
#
# Option examples:
# belongs_to :firm, foreign_key: "client_of"
@@ -1660,6 +1663,7 @@ module ActiveRecord
# belongs_to :comment, touch: true
# belongs_to :company, touch: :employees_last_updated_at
# belongs_to :user, optional: true
+ # belongs_to :account, default: -> { company.account }
def belongs_to(name, scope = nil, options = {})
reflection = Builder::BelongsTo.build(self, name, scope, options)
Reflection.add_reflection self, name, reflection
diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb
index 64b2311911..4a4f88bb94 100644
--- a/activerecord/lib/active_record/associations/belongs_to_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_association.rb
@@ -21,6 +21,10 @@ module ActiveRecord
self.target = record
end
+ def default(record)
+ writer(record) if reader.nil?
+ end
+
def reset
super
@updated = false
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb
index a1609ab0fb..50a1c39ccf 100644
--- a/activerecord/lib/active_record/associations/builder/belongs_to.rb
+++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb
@@ -5,7 +5,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
end
def self.valid_options(options)
- super + [:polymorphic, :touch, :counter_cache, :optional]
+ super + [:polymorphic, :touch, :counter_cache, :optional, :default]
end
def self.valid_dependent_options
@@ -16,6 +16,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
super
add_counter_cache_callbacks(model, reflection) if reflection.options[:counter_cache]
add_touch_callbacks(model, reflection) if reflection.options[:touch]
+ add_default_callbacks(model, reflection) if reflection.options[:default]
end
def self.define_accessors(mixin, reflection)
@@ -118,6 +119,12 @@ module ActiveRecord::Associations::Builder # :nodoc:
model.after_destroy callback.(:changes_to_save)
end
+ def self.add_default_callbacks(model, reflection)
+ model.before_validation lambda { |o|
+ o.association(reflection.name).default o.instance_exec(&reflection.options[:default])
+ }
+ end
+
def self.add_destroy_callbacks(model, reflection)
model.after_destroy lambda { |o| o.association(reflection.name).handle_dependency }
end