Skip to content

Commit 604034d

Browse files
committed
Extend ActiveRecord PredicateBuilder to support querying by polymorphic integer relations
1 parent e37bbee commit 604034d

3 files changed

Lines changed: 42 additions & 0 deletions

File tree

lib/polymorphic_integer_type.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require "polymorphic_integer_type/version"
22
require "polymorphic_integer_type/extensions"
33
require "polymorphic_integer_type/mapping"
4+
require "polymorphic_integer_type/predicate_builder_extension"
45

56
module PolymorphicIntegerType; end

lib/polymorphic_integer_type/extensions.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ def belongs_to(name, scope = nil, options = {})
1212
foreign_type = reflections[name.to_s].foreign_type
1313
self._polymorphic_foreign_types << foreign_type
1414

15+
# Required way to dynamically define a class method on the model
16+
singleton_class.__send__(:define_method, "#{foreign_type}_mapping") do
17+
mapping
18+
end
19+
1520
define_method foreign_type do
1621
t = super()
1722
mapping[t]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module PolymorphicIntegerType
2+
module PredicateBuilderExtension
3+
def self.expand(klass, table, column, value)
4+
queries = []
5+
6+
# Find the foreign key when using queries such as:
7+
# Post.where(author: author)
8+
#
9+
# For polymorphic relationships, find the foreign key and type:
10+
# PriceEstimate.where(estimate_of: treasure)
11+
if klass && reflection = klass._reflect_on_association(column)
12+
base_class = polymorphic_base_class_from_value(value)
13+
14+
if reflection.polymorphic? && base_class
15+
if klass.respond_to?("#{column}_type_mapping")
16+
queries << build(table[reflection.foreign_type], klass.send("#{column}_type_mapping").key(base_class.to_s))
17+
else
18+
queries << build(table[reflection.foreign_type], base_class)
19+
end
20+
end
21+
22+
column = reflection.foreign_key
23+
24+
if base_class
25+
primary_key = reflection.association_primary_key(base_class)
26+
value = convert_value_to_association_ids(value, primary_key)
27+
end
28+
end
29+
30+
queries << build(table[column], value)
31+
queries
32+
end
33+
end
34+
end
35+
36+
ActiveRecord::PredicateBuilder.prepend(PolymorphicIntegerType::PredicateBuilderExtension)

0 commit comments

Comments
 (0)