Class: ParamsReady::Pagination::CursorBuilder::Cursor
- Inherits:
-
Object
- Object
- ParamsReady::Pagination::CursorBuilder::Cursor
- Defined in:
- lib/params_ready/pagination/cursor.rb
Instance Attribute Summary collapse
-
#cte ⇒ Object
readonly
Returns the value of attribute cte.
-
#literals ⇒ Object
readonly
Returns the value of attribute literals.
-
#select_list ⇒ Object
readonly
Returns the value of attribute select_list.
-
#selectors ⇒ Object
readonly
Returns the value of attribute selectors.
Instance Method Summary collapse
- #active_record_predicates(literals) ⇒ Object
- #arel_predicates(literals, arel_table) ⇒ Object
- #column_expressions(selectors) ⇒ Object
- #column_names(selectors) ⇒ Object
- #cte_definition(reference, names) ⇒ Object
- #cte_for_query(query, arel_table) ⇒ Object
- #cte_for_relation(relation) ⇒ Object
- #cte_reference(names) ⇒ Object
-
#initialize(select_list, arel_table, context) ⇒ Cursor
constructor
A new instance of Cursor.
- #rvalue(key) ⇒ Object
- #select_list_to_hash(select_list) ⇒ Object
Constructor Details
#initialize(select_list, arel_table, context) ⇒ Cursor
Returns a new instance of Cursor.
77 78 79 80 81 82 83 84 85 86 87 |
# 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 |
Instance Attribute Details
#cte ⇒ Object (readonly)
Returns the value of attribute cte.
75 76 77 |
# File 'lib/params_ready/pagination/cursor.rb', line 75 def cte @cte end |
#literals ⇒ Object (readonly)
Returns the value of attribute literals.
75 76 77 |
# File 'lib/params_ready/pagination/cursor.rb', line 75 def literals @literals end |
#select_list ⇒ Object (readonly)
Returns the value of attribute select_list.
75 76 77 |
# File 'lib/params_ready/pagination/cursor.rb', line 75 def select_list @select_list end |
#selectors ⇒ Object (readonly)
Returns the value of attribute selectors.
75 76 77 |
# File 'lib/params_ready/pagination/cursor.rb', line 75 def selectors @selectors end |
Instance Method Details
#active_record_predicates(literals) ⇒ Object
121 122 123 124 125 126 127 |
# 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) ⇒ Object
129 130 131 132 133 134 135 136 137 138 |
# 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) ⇒ Object
144 145 146 147 148 |
# 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) ⇒ Object
140 141 142 |
# 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) ⇒ Object
155 156 157 158 159 160 161 162 163 |
# 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) ⇒ Object
110 111 112 113 114 115 116 117 118 119 |
# 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) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 |
# 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) ⇒ Object
150 151 152 153 |
# 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) ⇒ Object
165 166 167 |
# File 'lib/params_ready/pagination/cursor.rb', line 165 def rvalue(key) @hash[key].rvalue(@cte_ref) end |
#select_list_to_hash(select_list) ⇒ Object
89 90 91 92 93 94 95 96 |
# 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 |