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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2336d0d23d8af77f9f090bfd8962c25a8c97c9d9f39ffce7be9fe2034d7affc
4
- data.tar.gz: 191d8e607720235a354e4da42e640e0fd3ca5b29aca814c1a1a0531d75f01833
3
+ metadata.gz: ed9b99ff1ffc9ead0b84cead020b7abd3340b3b1ea85506ff51436469c8d38c8
4
+ data.tar.gz: e94ad2aec17f47227f2c590632266fda4d567fe757ed4eb7a139bd8e45d70c1a
5
5
  SHA512:
6
- metadata.gz: f0fd3bc2e744d3de0fcd7092bd87d5969d472c886eacc7d007ff711bae937449588b48cb7ed5e56f590756f6d0f214fee2b690bdc9ead7676453b7e64e8862e5
7
- data.tar.gz: 692abd2df6a29e0687f4aa4ad985ebf88371b5a72b7b45432d42e4837cc423272a98c15dc2a139bdebe7ac0a0d24a53b293b8f7f25e43081da1fc13013c555fd
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
- nodes = apply_condition(input, relation_table_being_queried, inverse_clause)
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
- # if can_use_where_in_relationship_subquery?(instance)
104
- # create_pending_wherein_subquery(input: input, relation: relation, instance: instance, query: query)
105
- # else
106
- # create_pending_has_many_through_subquery(input: input, relation: relation, instance: instance, query: query)
107
- # end
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 = if query.respond_to? :model
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)
@@ -1,6 +1,5 @@
1
1
  <% form_id = dom_id(@criterion, :form) %>
2
2
 
3
- <% puts "In New Turbo Stream" %>
4
3
  <%= turbo_stream.update dom_id(@criterion) do %>
5
4
  <%= render "refine/advanced_inline/filters/popup",
6
5
  frame_id: dom_id(@criterion), is_open: true do
@@ -1,5 +1,5 @@
1
1
  module Refine
2
2
  module Rails
3
- VERSION = "2.13.5"
3
+ VERSION = "2.13.7"
4
4
  end
5
5
  end
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.5
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-02-17 00:00:00.000000000 Z
12
+ date: 2025-03-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails