refine-rails 2.13.5 → 2.13.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/models/refine/conditions/condition.rb +1 -1
- data/app/models/refine/conditions/supports_flat_queries.rb +50 -13
- data/app/models/refine/conditions/uses_attributes.rb +11 -7
- data/app/models/refine/inspector.rb +7 -0
- data/app/models/refine/tracks_pending_relationship_subqueries.rb +1 -0
- data/app/views/refine/advanced_inline/criteria/new.turbo_stream.erb +0 -1
- data/lib/refine/rails/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed9b99ff1ffc9ead0b84cead020b7abd3340b3b1ea85506ff51436469c8d38c8
|
4
|
+
data.tar.gz: e94ad2aec17f47227f2c590632266fda4d567fe757ed4eb7a139bd8e45d70c1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 387b1428a0ac1d05da2291578c14b08b208499243c3f6c546afc437f62a932c343d675e1e0189337a752ed52cd3beef9e3f847f638ac238f08465e367629bad5
|
7
|
+
data.tar.gz: 436423c40e435a5c35290e5cc1572fc88f6ff4a57ba2e42b2370140811a52bcbf20ca8e1f4a046509292a3f9454de19b992baad4faf2792555535abc1c6c8d64
|
@@ -16,7 +16,7 @@ module Refine::Conditions
|
|
16
16
|
include SupportsFlatQueries
|
17
17
|
|
18
18
|
attr_reader :ensurances, :before_validations, :clause, :filter
|
19
|
-
attr_accessor :display, :id, :is_refinement, :attribute
|
19
|
+
attr_accessor :display, :id, :is_refinement, :attribute, :is_flat_query
|
20
20
|
|
21
21
|
I18N_PREFIX = "refine.refine_blueprints.condition."
|
22
22
|
|
@@ -15,8 +15,10 @@ module Refine::Conditions
|
|
15
15
|
# @param [ActiveRecord::Relation] initial_query The base query the query is built on
|
16
16
|
# @param [Bool] inverse_clause Whether to invert the clause
|
17
17
|
# @return [Arel::Node]
|
18
|
+
# This is mostly a copy of the `apply` method from the Condition module, but avoids recursion and the pending_subquery system
|
18
19
|
def apply_flat(input, table, initial_query, inverse_clause=false)
|
19
20
|
table ||= filter.table
|
21
|
+
@is_flat_query = true
|
20
22
|
# Ensurance validations are checking the developer configured correctly
|
21
23
|
run_ensurance_validations
|
22
24
|
# Allow developer to modify user input
|
@@ -27,6 +29,7 @@ module Refine::Conditions
|
|
27
29
|
# TODO Determine right place to set the clause
|
28
30
|
validate_user_input(input)
|
29
31
|
if input.dig(:filter_refinement).present?
|
32
|
+
# TODO - Handle refinements. Currently not working for flat queries because its dependent on the pending_subquery system
|
30
33
|
|
31
34
|
filter_condition = call_proc_if_callable(@filter_refinement_proc)
|
32
35
|
# Set the filter on the filter_condition to be the current_condition's filter
|
@@ -39,7 +42,7 @@ module Refine::Conditions
|
|
39
42
|
end
|
40
43
|
|
41
44
|
if is_relationship_attribute?
|
42
|
-
return handle_flat_relational_condition(input: input, query: initial_query, inverse_clause: inverse_clause)
|
45
|
+
return handle_flat_relational_condition(input: input, table: table, query: initial_query, inverse_clause: inverse_clause)
|
43
46
|
end
|
44
47
|
# Not a relationship attribute, apply condition normally
|
45
48
|
nodes = apply_condition(input, table, inverse_clause)
|
@@ -51,7 +54,7 @@ module Refine::Conditions
|
|
51
54
|
nodes
|
52
55
|
end
|
53
56
|
|
54
|
-
def handle_flat_relational_condition(input:, query:, inverse_clause:)
|
57
|
+
def handle_flat_relational_condition(input:, table:, query:, inverse_clause:)
|
55
58
|
# Split on first .
|
56
59
|
decompose_attribute = @attribute.split(".", 2)
|
57
60
|
# Attribute now is the back half of the initial attribute
|
@@ -71,20 +74,27 @@ module Refine::Conditions
|
|
71
74
|
end
|
72
75
|
|
73
76
|
through_reflection = instance
|
77
|
+
forced_id = false
|
74
78
|
|
75
79
|
# TODO - make sure we're accounting for refinements
|
76
80
|
if @attribute == "id"
|
77
81
|
# We're referencing a primary key ID, so we dont need the final join table and
|
78
82
|
# can just reference the foreign key of the previous step in the relation chain
|
79
83
|
through_reflection = get_through_reflection(instance: instance, relation: decompose_attribute[0])
|
84
|
+
unless condition_uses_different_database?(through_reflection.klass, query.model)
|
85
|
+
forced_id = true
|
86
|
+
@attribute = get_foreign_key_from_relation(instance: instance, reflection: through_reflection)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
unless condition_uses_different_database?(through_reflection.klass, query.model)
|
80
91
|
add_pending_joins_if_needed(instance: instance, reflection: through_reflection, input: input)
|
81
|
-
# TODO - this is not the right long-term place for this.
|
82
|
-
filter.needs_distinct = true
|
83
|
-
@attribute = get_foreign_key_from_relation(instance: instance, reflection: through_reflection)
|
84
|
-
else
|
85
|
-
puts "TODO - not referencing an ID in attribute"
|
86
92
|
end
|
93
|
+
# TODO - this is not the right long-term place for this.
|
94
|
+
apply_flat_relational_condition(instance: instance, relation: relation, through_reflection: through_reflection, input: input, table: table, query: query, inverse_clause: inverse_clause, forced_id: forced_id)
|
95
|
+
end
|
87
96
|
|
97
|
+
def apply_flat_relational_condition(instance:, relation:, through_reflection:, input:, table:, query:, inverse_clause:, forced_id: false)
|
88
98
|
unless instance
|
89
99
|
raise "Relationship does not exist for #{relation}."
|
90
100
|
end
|
@@ -92,19 +102,40 @@ module Refine::Conditions
|
|
92
102
|
relation_table_being_queried = through_reflection.klass.arel_table
|
93
103
|
relation_class = through_reflection.klass
|
94
104
|
|
95
|
-
|
105
|
+
instance = get_reflection_object(query, relation) if forced_id
|
106
|
+
|
107
|
+
key_1 = key_1(instance)
|
108
|
+
key_2 = key_2(instance)
|
109
|
+
if condition_uses_different_database?(relation_class, query.model)
|
110
|
+
nodes = handle_flat_cross_database_condition(input: input, table: table, relation_class: relation_class, relation_table_being_queried: relation_table_being_queried, inverse_clause: inverse_clause, key_1: key_1, key_2: key_2)
|
111
|
+
else
|
112
|
+
if forced_id
|
113
|
+
nodes = apply(input, relation_table_being_queried, query, inverse_clause, key_2)
|
114
|
+
else
|
115
|
+
nodes = apply(input, relation_table_being_queried, query, inverse_clause)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
96
119
|
if !is_refinement && has_any_refinements?
|
97
120
|
refined_node = apply_refinements(input)
|
98
121
|
# Count refinement will return nil because it directly modified pending relationship subquery
|
99
122
|
nodes = nodes.and(refined_node) if refined_node
|
100
123
|
end
|
101
124
|
nodes
|
125
|
+
end
|
102
126
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
127
|
+
# When we need to go to another DB for the relation. We need to do a separate query to get the IDS of
|
128
|
+
# the records matching the condition that will then be passed into the primary query.
|
129
|
+
def handle_flat_cross_database_condition(input:, table:, relation_class:, relation_table_being_queried:, inverse_clause:, key_1:, key_2:)
|
130
|
+
relational_query = relation_class.select(key_2).arel
|
131
|
+
node = apply(input, relation_table_being_queried, relation_class, inverse_clause)
|
132
|
+
relational_query = relational_query.where(node)
|
133
|
+
array_of_ids = relation_class.connection.exec_query(relational_query.to_sql).rows.flatten
|
134
|
+
if array_of_ids.length == 1
|
135
|
+
nodes = table[:"#{key_1}"].eq(array_of_ids.first)
|
136
|
+
else
|
137
|
+
nodes = table[:"#{key_1}"].in(array_of_ids)
|
138
|
+
end
|
108
139
|
end
|
109
140
|
|
110
141
|
def get_through_reflection(instance:, relation:)
|
@@ -129,6 +160,7 @@ module Refine::Conditions
|
|
129
160
|
# If we already are tracking the relation with a left joins, don't overwrite it
|
130
161
|
# puts "adding a pending join for relation: #{relation} with join type: #{join_type}"
|
131
162
|
unless join_type == :inner && filter.pending_joins[relation] == :left
|
163
|
+
filter.needs_distinct = true
|
132
164
|
filter.pending_joins[relation] = join_type
|
133
165
|
end
|
134
166
|
end
|
@@ -141,5 +173,10 @@ module Refine::Conditions
|
|
141
173
|
add_pending_join(reflection.name, :inner)
|
142
174
|
end
|
143
175
|
end
|
176
|
+
|
177
|
+
def condition_uses_different_database?(current_model, parent_model)
|
178
|
+
# Are the queries on different databases?
|
179
|
+
parent_model.connection_db_config.configuration_hash != current_model.connection_db_config.configuration_hash
|
180
|
+
end
|
144
181
|
end
|
145
182
|
end
|
@@ -21,13 +21,7 @@ module Refine::Conditions
|
|
21
21
|
|
22
22
|
# Get the Reflection object which defines the relationship between query and relation
|
23
23
|
# First iteration pull relationship using base query which responds to model.
|
24
|
-
instance =
|
25
|
-
query.model.reflect_on_association(relation.to_sym)
|
26
|
-
else
|
27
|
-
# When query is sent in as subquery (recursive) the query object is the model class pulled from the
|
28
|
-
# previous instance value
|
29
|
-
query.reflect_on_association(relation.to_sym)
|
30
|
-
end
|
24
|
+
instance = get_reflection_object(query, relation)
|
31
25
|
|
32
26
|
unless instance
|
33
27
|
raise "Relationship does not exist for #{relation}."
|
@@ -69,6 +63,16 @@ module Refine::Conditions
|
|
69
63
|
end
|
70
64
|
end
|
71
65
|
|
66
|
+
def get_reflection_object(query, relation)
|
67
|
+
if query.respond_to? :model
|
68
|
+
query.model.reflect_on_association(relation.to_sym)
|
69
|
+
else
|
70
|
+
# When query is sent in as subquery (recursive) the query object is the model class pulled from the
|
71
|
+
# previous instance value
|
72
|
+
query.reflect_on_association(relation.to_sym)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
72
76
|
def create_pending_wherein_subquery(input:, relation:, instance:, query:)
|
73
77
|
# This method builds out the linking keys between the provided query model and the relation
|
74
78
|
# and saves it to pending relationship subqueries
|
@@ -37,5 +37,12 @@ module Refine
|
|
37
37
|
@blueprint.select{|c| c[:type] == "criterion" && negative_clauses.include?(c[:input][:clause])}.any?
|
38
38
|
end
|
39
39
|
|
40
|
+
def has_duplicate_conditions?
|
41
|
+
return false if @blueprint.nil? || @blueprint.empty?
|
42
|
+
conditions = @blueprint.select{|c| c[:type] == "criterion"}
|
43
|
+
condition_ids = conditions.map{|c| c[:condition_id]}
|
44
|
+
condition_ids.length != condition_ids.uniq.length
|
45
|
+
end
|
46
|
+
|
40
47
|
end
|
41
48
|
end
|
@@ -116,6 +116,7 @@ module Refine
|
|
116
116
|
subset.each do |relation, subquery|
|
117
117
|
# relation = table
|
118
118
|
# subquery.keys = [:instance, :query, :key, :secondary] possibly (:children)
|
119
|
+
|
119
120
|
if subquery.dig(:children).present?
|
120
121
|
# Send in the values at children as the subset hash and remove from existing subquery
|
121
122
|
child_nodes = subquery.delete(:children)
|
data/lib/refine/rails/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: refine-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.13.
|
4
|
+
version: 2.13.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Colleen Schnettler
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-
|
12
|
+
date: 2025-03-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|