Module: AppQuery::RenderHelpers
- Defined in:
- lib/app_query/render_helpers.rb
Overview
These methods require +@collected_binds+ (Hash) and +@placeholder_counter+ (Integer) instance variables to be initialized in the including context.
Provides helper methods for rendering SQL templates in ERB.
These helpers are available within ERB templates when using Q#render. They provide safe SQL construction with parameterized queries.
Instance Method Summary collapse
-
#bind(value) ⇒ String
Creates a named bind parameter placeholder and collects the value.
-
#order_by(hash) ⇒ String
Generates an ORDER BY clause from a hash of column directions.
-
#quote(value) ⇒ String
Quotes a value for safe inclusion in SQL using ActiveRecord's quoting.
-
#values(coll, skip_columns: false) {|item| ... } ⇒ String
Generates a SQL VALUES clause from a collection with automatic bind parameters.
Instance Method Details
#bind(value) ⇒ String
Creates a named bind parameter placeholder and collects the value.
This is the preferred way to include dynamic values in SQL queries. The value is collected internally and a placeholder (e.g., +:b1+) is returned for insertion into the SQL template.
65 66 67 |
# File 'lib/app_query/render_helpers.rb', line 65 def bind(value) collect_bind(value) end |
#order_by(hash) ⇒ String
The hash must not be blank. Use conditional ERB for optional ordering.
Generates an ORDER BY clause from a hash of column directions.
Converts a hash of column names and sort directions into a valid SQL ORDER BY clause.
179 180 181 182 183 184 |
# File 'lib/app_query/render_helpers.rb', line 179 def order_by(hash) raise ArgumentError, "Provide columns to sort by, e.g. order_by(id: :asc) (got #{hash.inspect})." unless hash.present? "ORDER BY " + hash.map do |k, v| v.nil? ? k : [k, v.upcase].join(" ") end.join(", ") end |
#quote(value) ⇒ String
Prefer #bind for parameterized queries when possible, as it provides better security and query plan caching.
Quotes a value for safe inclusion in SQL using ActiveRecord's quoting.
Use this helper when you need to embed a literal value directly in SQL rather than using a bind parameter. This is useful for values that need to be visible in the SQL string itself.
38 39 40 |
# File 'lib/app_query/render_helpers.rb', line 38 def quote(value) ActiveRecord::Base.connection.quote(value) end |
#values(coll, skip_columns: false) {|item| ... } ⇒ String
Generates a SQL VALUES clause from a collection with automatic bind parameters.
Supports three input formats:
- Array of Arrays - Simple row data without column names
- Array of Hashes - Row data with automatic column name extraction
- Collection with block - Custom value transformation per row
TODO: Add types: parameter to cast bind placeholders (needed for UNION ALL where PG can't infer types). E.g. values([[1]], types: [:integer]) would generate VALUES (:b1::integer)
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/app_query/render_helpers.rb', line 115 def values(coll, skip_columns: false, &block) first = coll.first # For hash collections, collect all unique keys if first.is_a?(Hash) && !block all_keys = coll.flat_map(&:keys).uniq rows = coll.map do |row| vals = all_keys.map { |k| row.key?(k) ? collect_bind(row[k]) : "NULL" } "(#{vals.join(", ")})" end columns = skip_columns ? "" : "(#{all_keys.join(", ")}) " "#{columns}VALUES #{rows.join(",\n")}" else # Arrays or block - current behavior rows = coll.map do |item| vals = if block block.call(item) elsif item.is_a?(Array) item.map { |v| collect_bind(v) } else [collect_bind(item)] end "(#{vals.join(", ")})" end "VALUES #{rows.join(",\n")}" end end |