Last active
August 29, 2015 14:08
-
-
Save TikiTDO/bda28aa2bc387489e2af to your computer and use it in GitHub Desktop.
Fixes to make poly int type work with where requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module PolymorphicIntegerWhere | |
class Railtie < Rails::Railtie | |
initializer "PolymorphicInteger.active_record" do | |
::PolymorphicIntegerType::Extensions::ClassMethods.class_eval do | |
prepend ForcePolymorphicInteger | |
end | |
::ActiveRecord::Associations::BelongsToPolymorphicAssociation.class_eval do | |
prepend InjectBelongsToPolymorphicAssociation | |
end | |
::ActiveRecord::PredicateBuilder.class_eval do | |
class << self | |
prepend InjectPredicateBuilder | |
end | |
end | |
end | |
end | |
module ForcePolymorphicInteger | |
force_poly = proc do |name, scope_or_options = nil, options = {}, &block| | |
# Organize scope and options | |
if scope_or_options.kind_of? Hash | |
options, scope = scope_or_options, nil | |
else | |
scope = scope_or_options | |
end | |
# Ensure polymorphic assoc are integer types | |
if (options[:polymorphic] || options[:as]) && (!options[:integer_type]) | |
raise "Add [integer_type: true] to #{self.name}##{name} polymorphic association" | |
end | |
# Pass on control | |
super name, scope, options, &block | |
end | |
define_method :belongs_to, &force_poly | |
define_method :has_one, &force_poly | |
define_method :has_many, &force_poly | |
end | |
module InjectBelongsToPolymorphicAssociation | |
# Might not be necessary | |
# def klass | |
# return super | |
# if reflection.active_record < PolymorphicIntegerType::Extensions | |
# mapping = PolymorphicIntegerType::Mapping[reflection.name] | |
# type = mapping[owner[reflection.foreign_type]] | |
# type.presence && type.constantize | |
# else | |
# super | |
# end | |
# end | |
end | |
module InjectPredicateBuilder | |
# Overwrite code that builds the right ordinal of a polymorphic request. | |
# Caution: This also builds a lot of other things | |
def build(attribute, value) | |
ret = super | |
# Special handling for PolyInt classes | |
target_class = attribute.relation.engine | |
if target_class < PolymorphicIntegerType::Extensions | |
# Reset the polymorphic cache on file reload | |
if !@__poly_assoc_cache | |
@__poly_assoc_cache = {} | |
ActionDispatch::Reloader.to_prepare { @__poly_assoc_cache = {} } | |
end | |
# Generate the polymorphic cache to speed query generation | |
@__poly_assoc_cache[target_class] ||= target_class.reflections.map do |k, v| | |
if v.polymorphic? then [v.foreign_type, k] else [nil, nil] end | |
end.to_h | |
# Check if this request need poly int processing | |
poly_assoc_name = @__poly_assoc_cache[target_class][attribute.name] | |
if poly_assoc_name | |
poly_assoc_name = poly_assoc_name.to_sym | |
mapping = PolymorphicIntegerType::Mapping[poly_assoc_name] | |
result = (mapping||{ret.right => ret.right}).key ret.right | |
ret.right = result if result | |
end | |
end | |
# Done processing, return the result | |
ret | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment