Skip to content

Commit

Permalink
Refactor Condition
Browse files Browse the repository at this point in the history
  • Loading branch information
scarroll32 committed Nov 9, 2022
1 parent a7d93fa commit 0353ae1
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 86 deletions.
1 change: 0 additions & 1 deletion lib/ransack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class UntraversableAssociationError < StandardError; end
require 'ransack/ransacker'
require 'ransack/translate'
require 'ransack/adapters/active_record'
require 'ransack/adapters/active_record/ransack/nodes/condition'
require 'ransack/context'

ActiveSupport.on_load(:action_controller) do
Expand Down
83 changes: 0 additions & 83 deletions lib/ransack/adapters/active_record/ransack/nodes/condition.rb

This file was deleted.

1 change: 0 additions & 1 deletion lib/ransack/nodes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
require 'ransack/nodes/attribute'
require 'ransack/nodes/value'
require 'ransack/nodes/condition'
require 'ransack/adapters/active_record/ransack/nodes/condition'
require 'ransack/nodes/sort'
require 'ransack/nodes/grouping'
75 changes: 74 additions & 1 deletion lib/ransack/nodes/condition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -283,12 +283,85 @@ def negative?
predicate.negative?
end

def arel_predicate
predicate = attributes.map { |attribute|
association = attribute.parent
if negative? && attribute.associated_collection?
query = context.build_correlated_subquery(association)
context.remove_association(association)
if self.predicate_name == 'not_null' && self.value
query.where(format_predicate(attribute))
Arel::Nodes::In.new(context.primary_key, Arel.sql(query.to_sql))
else
query.where(format_predicate(attribute).not)
Arel::Nodes::NotIn.new(context.primary_key, Arel.sql(query.to_sql))
end
else
format_predicate(attribute)
end
}.reduce(combinator_method)

if replace_right_node?(predicate)
# Replace right node object to plain integer value in order to avoid
# ActiveModel::RangeError from Arel::Node::Casted.
# The error can be ignored here because RDBMSs accept large numbers
# in condition clauses.
plain_value = predicate.right.value
predicate.right = plain_value
end

predicate
end

private

def combinator_method
combinator === Constants::OR ? :or : :and
end

def format_predicate(attribute)
arel_pred = arel_predicate_for_attribute(attribute)
arel_values = formatted_values_for_attribute(attribute)
predicate = attr_value_for_attribute(attribute).public_send(arel_pred, arel_values)

if in_predicate?(predicate)
predicate.right = predicate.right.map do |pr|
casted_array?(pr) ? format_values_for(pr) : pr
end
end

predicate
end

def in_predicate?(predicate)
return unless defined?(Arel::Nodes::Casted)
predicate.class == Arel::Nodes::In || predicate.class == Arel::Nodes::NotIn
end

def casted_array?(predicate)
predicate.value.is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted)
end

def format_values_for(predicate)
predicate.value.map do |val|
val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val
end
end

def replace_right_node?(predicate)
return false unless predicate.is_a?(Arel::Nodes::Binary)

arel_node = predicate.right
return false unless arel_node.is_a?(Arel::Nodes::Casted)

relation, name = arel_node.attribute.values
attribute_type = relation.type_for_attribute(name).type
attribute_type == :integer && arel_node.value.is_a?(Integer)
end

def valid_combinator?
attributes.size < 2 || Constants::AND_OR.include?(combinator)
end

end
end
end

0 comments on commit 0353ae1

Please sign in to comment.