class ParamsReady::Pagination::CursorBuilder::Cursor
Attributes
cte[R]
literals[R]
select_list[R]
selectors[R]
Public Class Methods
new(select_list, arel_table, context)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 77 def initialize(select_list, arel_table, context) @hash = select_list_to_hash(select_list) @selectors, @literals = select_list.partition { |attr| attr.is_a? Selector } @arel_table = arel_table @context = context names = column_names(@selectors) @cte_ref = Arel::Table.new(cte_reference(names)) @cte_def = cte_definition(@cte_ref, names) freeze end
Public Instance Methods
active_record_predicates(literals)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 121 def active_record_predicates(literals) literals.select do |literal| literal.pk end.map do |literal| [literal.key, literal.value] end.to_h end
arel_predicates(literals, arel_table)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 129 def arel_predicates(literals, arel_table) literals.reduce(nil) do |query, literal| next query unless literal.pk predicate = arel_table[literal.key].eq(literal.quoted) next predicate if query.nil? query.and(predicate) end end
column_expressions(selectors)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 144 def column_expressions(selectors) selectors.map do |selector| selector.expression(@arel_table, @context) end end
column_names(selectors)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 140 def column_names(selectors) selectors.lazy.map(&:key).map(&:to_s).force end
cte_definition(reference, names)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 155 def cte_definition(reference, names) node = Arel::Nodes::SqlLiteral.new(names.join(', ')) grouping = Arel::Nodes::Grouping.new(node) # The name must be literal, otherwise # it will be quoted by the visitor expression = "#{reference.name} #{grouping.to_sql}" Arel::Nodes::CteName.new(expression) end
cte_for_query(query, arel_table)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 110 def cte_for_query(query, arel_table) return nil if selectors.empty? query = query.deep_dup expressions = column_expressions(selectors) query = query.where(arel_predicates(literals, arel_table)) .project(*expressions) grouping = Arel::Nodes::Grouping.new(query) Arel::Nodes::As.new(@cte_def, grouping) end
cte_for_relation(relation)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 98 def cte_for_relation(relation) return nil if selectors.empty? expressions = column_expressions(selectors) relation = relation.where(**active_record_predicates(literals)) .select(*expressions) select = Arel::Nodes::SqlLiteral.new(relation.to_sql) grouping = Arel::Nodes::Grouping.new(select) as = Arel::Nodes::As.new(@cte_def, grouping) Arel::Nodes::With.new([as]) end
cte_reference(names)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 150 def cte_reference(names) unsafe_name = "#{names.join('_')}_cte" Helpers::ArelBuilder.safe_name(unsafe_name) end
rvalue(key)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 165 def rvalue(key) @hash[key].rvalue(@cte_ref) end
select_list_to_hash(select_list)
click to toggle source
# File lib/params_ready/pagination/cursor.rb, line 89 def select_list_to_hash(select_list) res = select_list.each_with_object({}) do |item, hash| raise ParamsReadyError, "Repeated key in select list: '#{item.key}'" if hash.key? item.key hash[item.key] = item end res.freeze end