Skip to content

Commit

Permalink
Merge branch 'builder-instances'
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelfranca committed Oct 9, 2013
2 parents ad0030b + 2a10a1e commit ebe9cd8
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 59 deletions.
47 changes: 24 additions & 23 deletions activerecord/lib/active_record/associations/builder/association.rb
Expand Up @@ -18,57 +18,60 @@ class << self


VALID_OPTIONS = [:class_name, :class, :foreign_key, :validate] VALID_OPTIONS = [:class_name, :class, :foreign_key, :validate]


attr_reader :name, :scope, :options

def self.build(model, name, scope, options, &block) def self.build(model, name, scope, options, &block)
builder = create_builder model, name, scope, options, &block extension = define_extensions model, name, &block
reflection = builder.build(model) reflection = create_reflection model, name, scope, options, extension
define_accessors model, reflection define_accessors model, reflection
define_callbacks model, reflection define_callbacks model, reflection
builder.define_extensions model
reflection reflection
end end


def self.create_builder(model, name, scope, options, &block) def self.create_reflection(model, name, scope, options, extension = nil)
raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol) raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol)


if scope.is_a?(Hash) if scope.is_a?(Hash)
options = scope options = scope
scope = nil scope = nil
end end


new(name, scope, options, &block) validate_options(options)
end
scope = build_scope(scope, extension)


def initialize(name, scope, options) ActiveRecord::Reflection.create(macro, name, scope, options, model)
@name = name end
@scope = scope
@options = options


validate_options def self.build_scope(scope, extension)
new_scope = scope


if scope && scope.arity == 0 if scope && scope.arity == 0
@scope = proc { instance_exec(&scope) } new_scope = proc { instance_exec(&scope) }
end end

if extension
new_scope = wrap_scope new_scope, extension
end

new_scope
end end


def build(model) def self.wrap_scope(scope, extension)
ActiveRecord::Reflection.create(macro, name, scope, options, model) scope
end end


def macro def self.macro
raise NotImplementedError raise NotImplementedError
end end


def valid_options def self.valid_options(options)
VALID_OPTIONS + Association.extensions.flat_map(&:valid_options) VALID_OPTIONS + Association.extensions.flat_map(&:valid_options)
end end


def validate_options def self.validate_options(options)
options.assert_valid_keys(valid_options) options.assert_valid_keys(valid_options(options))
end end


def define_extensions(model) def self.define_extensions(model, name)
end end


def self.define_callbacks(model, reflection) def self.define_callbacks(model, reflection)
Expand Down Expand Up @@ -111,8 +114,6 @@ def self.valid_dependent_options
raise NotImplementedError raise NotImplementedError
end end


private

def self.add_before_destroy_callbacks(model, reflection) def self.add_before_destroy_callbacks(model, reflection)
unless valid_dependent_options.include? reflection.options[:dependent] unless valid_dependent_options.include? reflection.options[:dependent]
raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{reflection.options[:dependent]}" raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{reflection.options[:dependent]}"
Expand Down
@@ -1,10 +1,10 @@
module ActiveRecord::Associations::Builder module ActiveRecord::Associations::Builder
class BelongsTo < SingularAssociation #:nodoc: class BelongsTo < SingularAssociation #:nodoc:
def macro def self.macro
:belongs_to :belongs_to
end end


def valid_options def self.valid_options(options)
super + [:foreign_type, :polymorphic, :touch] super + [:foreign_type, :polymorphic, :touch]
end end


Expand All @@ -23,8 +23,6 @@ def self.define_accessors(mixin, reflection)
add_counter_cache_methods mixin add_counter_cache_methods mixin
end end


private

def self.add_counter_cache_methods(mixin) def self.add_counter_cache_methods(mixin)
return if mixin.method_defined? :belongs_to_counter_cache_after_create return if mixin.method_defined? :belongs_to_counter_cache_after_create


Expand Down
Expand Up @@ -7,22 +7,11 @@ class CollectionAssociation < Association #:nodoc:


CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove] CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]


def valid_options def self.valid_options(options)
super + [:table_name, :before_add, super + [:table_name, :before_add,
:after_add, :before_remove, :after_remove, :extend] :after_add, :before_remove, :after_remove, :extend]
end end


attr_reader :block_extension

def initialize(name, scope, options)
super
@mod = nil
if block_given?
@mod = Module.new(&Proc.new)
@scope = wrap_scope @scope, @mod
end
end

def self.define_callbacks(model, reflection) def self.define_callbacks(model, reflection)
super super
name = reflection.name name = reflection.name
Expand All @@ -32,10 +21,11 @@ def self.define_callbacks(model, reflection)
} }
end end


def define_extensions(model) def self.define_extensions(model, name)
if @mod if block_given?
extension_module_name = "#{model.name.demodulize}#{name.to_s.camelize}AssociationExtension" extension_module_name = "#{model.name.demodulize}#{name.to_s.camelize}AssociationExtension"
model.parent.const_set(extension_module_name, @mod) extension = Module.new(&Proc.new)
model.parent.const_set(extension_module_name, extension)
end end
end end


Expand Down Expand Up @@ -78,9 +68,7 @@ def #{name.to_s.singularize}_ids=(ids)
CODE CODE
end end


private def self.wrap_scope(scope, mod)

def wrap_scope(scope, mod)
if scope if scope
proc { |owner| instance_exec(owner, &scope).extending(mod) } proc { |owner| instance_exec(owner, &scope).extending(mod) }
else else
Expand Down
Expand Up @@ -84,11 +84,11 @@ def middle_reflection(join_model)
middle_name = [lhs_model.name.downcase.pluralize, middle_name = [lhs_model.name.downcase.pluralize,
association_name].join('_').gsub(/::/, '_').to_sym association_name].join('_').gsub(/::/, '_').to_sym
middle_options = middle_options join_model middle_options = middle_options join_model
hm_builder = HasMany.create_builder(lhs_model,
middle_name, HasMany.create_reflection(lhs_model,
nil, middle_name,
middle_options) nil,
hm_builder.build lhs_model middle_options)
end end


private private
Expand Down
@@ -1,10 +1,10 @@
module ActiveRecord::Associations::Builder module ActiveRecord::Associations::Builder
class HasMany < CollectionAssociation #:nodoc: class HasMany < CollectionAssociation #:nodoc:
def macro def self.macro
:has_many :has_many
end end


def valid_options def self.valid_options(options)
super + [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache] super + [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache]
end end


Expand Down
@@ -1,10 +1,10 @@
module ActiveRecord::Associations::Builder module ActiveRecord::Associations::Builder
class HasOne < SingularAssociation #:nodoc: class HasOne < SingularAssociation #:nodoc:
def macro def self.macro
:has_one :has_one
end end


def valid_options def self.valid_options(options)
valid = super + [:order, :as] valid = super + [:order, :as]
valid += [:through, :source, :source_type] if options[:through] valid += [:through, :source, :source_type] if options[:through]
valid valid
Expand All @@ -14,8 +14,6 @@ def self.valid_dependent_options
[:destroy, :delete, :nullify, :restrict_with_error, :restrict_with_exception] [:destroy, :delete, :nullify, :restrict_with_error, :restrict_with_exception]
end end


private

def self.add_before_destroy_callbacks(model, reflection) def self.add_before_destroy_callbacks(model, reflection)
super unless reflection.options[:through] super unless reflection.options[:through]
end end
Expand Down
Expand Up @@ -2,7 +2,7 @@


module ActiveRecord::Associations::Builder module ActiveRecord::Associations::Builder
class SingularAssociation < Association #:nodoc: class SingularAssociation < Association #:nodoc:
def valid_options def self.valid_options(options)
super + [:remote, :dependent, :counter_cache, :primary_key, :inverse_of] super + [:remote, :dependent, :counter_cache, :primary_key, :inverse_of]
end end


Expand Down
3 changes: 1 addition & 2 deletions activerecord/test/cases/associations/extension_test.rb
Expand Up @@ -75,7 +75,6 @@ def test_proxy_association_after_scoped
private private


def extend!(model) def extend!(model)
builder = ActiveRecord::Associations::Builder::HasMany.new(:association_name, nil, {}) { } ActiveRecord::Associations::Builder::HasMany.define_extensions(model, :association_name) { }
builder.define_extensions(model)
end end
end end

0 comments on commit ebe9cd8

Please sign in to comment.