diff options
author | Jon Leighton <j@jonathanleighton.com> | 2011-02-21 01:09:41 +0000 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2011-02-21 10:16:15 -0800 |
commit | 52f8e4b9dae6137fcd95793dffc26ddff80b623e (patch) | |
tree | 11a80259a618472810155ca46fd826246aab9906 /activerecord/lib/active_record/associations/builder/belongs_to.rb | |
parent | a5274bb52c058bae69476bee3c95f472513a5725 (diff) | |
download | rails-52f8e4b9dae6137fcd95793dffc26ddff80b623e.tar.gz rails-52f8e4b9dae6137fcd95793dffc26ddff80b623e.tar.bz2 rails-52f8e4b9dae6137fcd95793dffc26ddff80b623e.zip |
Use proper objects to do the work to build the associations (adding methods, callbacks etc) rather than calling a whole bunch of methods with rather long names.
Diffstat (limited to 'activerecord/lib/active_record/associations/builder/belongs_to.rb')
-rw-r--r-- | activerecord/lib/active_record/associations/builder/belongs_to.rb | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb new file mode 100644 index 0000000000..964e7fddc8 --- /dev/null +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -0,0 +1,83 @@ +module ActiveRecord::Associations::Builder + class BelongsTo < SingularAssociation #:nodoc: + self.macro = :belongs_to + + self.valid_options += [:foreign_type, :polymorphic, :touch] + + def constructable? + !options[:polymorphic] + end + + def build + reflection = super + add_counter_cache_callbacks(reflection) if options[:counter_cache] + add_touch_callbacks(reflection) if options[:touch] + configure_dependency + reflection + end + + private + + def add_counter_cache_callbacks(reflection) + cache_column = reflection.counter_cache_column + name = self.name + + method_name = "belongs_to_counter_cache_after_create_for_#{name}" + model.redefine_method(method_name) do + record = send(name) + record.class.increment_counter(cache_column, record.id) unless record.nil? + end + model.after_create(method_name) + + method_name = "belongs_to_counter_cache_before_destroy_for_#{name}" + model.redefine_method(method_name) do + record = send(name) + record.class.decrement_counter(cache_column, record.id) unless record.nil? + end + model.before_destroy(method_name) + + model.send(:module_eval, + "#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)", __FILE__, __LINE__ + ) + end + + def add_touch_callbacks(reflection) + name = self.name + method_name = "belongs_to_touch_after_save_or_destroy_for_#{name}" + touch = options[:touch] + + model.redefine_method(method_name) do + record = send(name) + + unless record.nil? + if touch == true + record.touch + else + record.touch(touch) + end + end + end + + model.after_save(method_name) + model.after_touch(method_name) + model.after_destroy(method_name) + end + + def configure_dependency + if options[:dependent] + unless [:destroy, :delete].include?(options[:dependent]) + raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{options[:dependent].inspect})" + end + + method_name = "belongs_to_dependent_#{options[:dependent]}_for_#{name}" + model.send(:class_eval, <<-eoruby, __FILE__, __LINE__ + 1) + def #{method_name} + association = #{name} + association.#{options[:dependent]} if association + end + eoruby + model.after_destroy method_name + end + end + end +end |