Class: Dorm::QueryBuilder
- Inherits:
-
Object
- Object
- Dorm::QueryBuilder
- Defined in:
- lib/dorm/query_builder.rb
Instance Attribute Summary collapse
-
#data_class ⇒ Object
readonly
Returns the value of attribute data_class.
-
#table_name ⇒ Object
readonly
Returns the value of attribute table_name.
Instance Method Summary collapse
- #add_hash_conditions(hash) ⇒ Object
- #add_where_condition(condition, params) ⇒ Object
- #avg(field) ⇒ Object
- #count ⇒ Object
- #execute ⇒ Object
- #exists? ⇒ Boolean
- #first ⇒ Object
-
#group_by(*fields) ⇒ Object
GROUP BY and HAVING.
- #having(condition, *params) ⇒ Object
-
#initialize(table_name, data_class) ⇒ QueryBuilder
constructor
A new instance of QueryBuilder.
- #inner_join(table, condition = nil, **kwargs) ⇒ Object
-
#join(table, condition = nil, **kwargs) ⇒ Object
JOIN methods.
- #left_join(table, condition = nil, **kwargs) ⇒ Object
-
#limit(count) ⇒ Object
LIMIT and OFFSET.
- #max(field) ⇒ Object
- #min(field) ⇒ Object
- #offset(count) ⇒ Object
- #order(field, direction = :asc) ⇒ Object
-
#order_by(*fields) ⇒ Object
ORDER BY.
-
#page(page_num, per_page = 20) ⇒ Object
Pagination helpers.
- #right_join(table, condition = nil, **kwargs) ⇒ Object
-
#select(*fields) ⇒ Object
SELECT methods.
- #select_raw(sql) ⇒ Object
-
#sum(field) ⇒ Object
Aggregation methods.
- #to_a ⇒ Object
-
#to_sql ⇒ Object
Execution methods.
-
#where(conditions = nil, **kwargs, &block) ⇒ Object
WHERE methods.
- #where_raw(sql, *params) ⇒ Object
Constructor Details
#initialize(table_name, data_class) ⇒ QueryBuilder
Returns a new instance of QueryBuilder.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/dorm/query_builder.rb', line 7 def initialize(table_name, data_class) @table_name = table_name @data_class = data_class @select_fields = ["#{table_name}.*"] @joins = [] @where_conditions = [] @group_by_fields = [] @having_conditions = [] @order_by_fields = [] @limit_value = nil @offset_value = nil @params = [] @param_counter = 0 end |
Instance Attribute Details
#data_class ⇒ Object (readonly)
Returns the value of attribute data_class.
5 6 7 |
# File 'lib/dorm/query_builder.rb', line 5 def data_class @data_class end |
#table_name ⇒ Object (readonly)
Returns the value of attribute table_name.
5 6 7 |
# File 'lib/dorm/query_builder.rb', line 5 def table_name @table_name end |
Instance Method Details
#add_hash_conditions(hash) ⇒ Object
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/dorm/query_builder.rb', line 222 def add_hash_conditions(hash) hash.each do |field, value| if value.is_a?(Array) placeholders = value.map { next_placeholder }.join(", ") @where_conditions << ["#{format_field(field)} IN (#{placeholders})", value] elsif value.is_a?(Range) condition = "#{format_field(field)} BETWEEN #{next_placeholder} AND #{next_placeholder}" @where_conditions << [condition, [value.begin, value.end]] elsif value.nil? @where_conditions << ["#{format_field(field)} IS NULL", []] else condition = "#{format_field(field)} = #{next_placeholder}" @where_conditions << [condition, [value]] end end end |
#add_where_condition(condition, params) ⇒ Object
218 219 220 |
# File 'lib/dorm/query_builder.rb', line 218 def add_where_condition(condition, params) @where_conditions << [condition, params] end |
#avg(field) ⇒ Object
200 201 202 203 204 |
# File 'lib/dorm/query_builder.rb', line 200 def avg(field) select_raw("AVG(#{format_field(field)}) as avg") .execute .map { |results| results.first&.[]("avg")&.to_f || 0 } end |
#count ⇒ Object
164 165 166 167 168 169 170 |
# File 'lib/dorm/query_builder.rb', line 164 def count select_raw("COUNT(*) as count") .limit(nil) .offset(nil) .execute .map { |results| results.first&.[]("count")&.to_i || 0 } end |
#execute ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/dorm/query_builder.rb', line 179 def execute Result.try do sql, params = build_sql_with_params result = Database.query(sql, params) case result when ->(r) { r.respond_to?(:map) } result.map { |row| row_to_data(row) } else [row_to_data(result)] end end end |
#exists? ⇒ Boolean
172 173 174 175 176 177 |
# File 'lib/dorm/query_builder.rb', line 172 def exists? select_raw("1") .limit(1) .execute .map { |results| !results.empty? } end |
#first ⇒ Object
157 158 159 160 161 162 |
# File 'lib/dorm/query_builder.rb', line 157 def first limit(1).execute.bind do |results| result = results.first result ? Result.success(result) : Result.failure("No records found") end end |
#group_by(*fields) ⇒ Object
GROUP BY and HAVING
94 95 96 97 98 99 100 |
# File 'lib/dorm/query_builder.rb', line 94 def group_by(*fields) clone.tap do |query| formatted_fields = fields.map { |f| format_field(f) } query.instance_variable_set(:@group_by_fields, query.instance_variable_get(:@group_by_fields) + formatted_fields) end end |
#having(condition, *params) ⇒ Object
102 103 104 105 106 107 108 |
# File 'lib/dorm/query_builder.rb', line 102 def having(condition, *params) clone.tap do |query| query.instance_variable_get(:@having_conditions) << [condition, params] query.instance_variable_set(:@param_counter, query.instance_variable_get(:@param_counter) + params.length) end end |
#inner_join(table, condition = nil, **kwargs) ⇒ Object
89 90 91 |
# File 'lib/dorm/query_builder.rb', line 89 def inner_join(table, condition = nil, **kwargs) add_join("INNER JOIN", table, condition, kwargs) end |
#join(table, condition = nil, **kwargs) ⇒ Object
JOIN methods
77 78 79 |
# File 'lib/dorm/query_builder.rb', line 77 def join(table, condition = nil, **kwargs) add_join("INNER JOIN", table, condition, kwargs) end |
#left_join(table, condition = nil, **kwargs) ⇒ Object
81 82 83 |
# File 'lib/dorm/query_builder.rb', line 81 def left_join(table, condition = nil, **kwargs) add_join("LEFT JOIN", table, condition, kwargs) end |
#limit(count) ⇒ Object
LIMIT and OFFSET
130 131 132 133 134 |
# File 'lib/dorm/query_builder.rb', line 130 def limit(count) clone.tap do |query| query.instance_variable_set(:@limit_value, count) end end |
#max(field) ⇒ Object
206 207 208 209 210 |
# File 'lib/dorm/query_builder.rb', line 206 def max(field) select_raw("MAX(#{format_field(field)}) as max") .execute .map { |results| results.first&.[]("max") } end |
#min(field) ⇒ Object
212 213 214 215 216 |
# File 'lib/dorm/query_builder.rb', line 212 def min(field) select_raw("MIN(#{format_field(field)}) as min") .execute .map { |results| results.first&.[]("min") } end |
#offset(count) ⇒ Object
136 137 138 139 140 |
# File 'lib/dorm/query_builder.rb', line 136 def offset(count) clone.tap do |query| query.instance_variable_set(:@offset_value, count) end end |
#order(field, direction = :asc) ⇒ Object
125 126 127 |
# File 'lib/dorm/query_builder.rb', line 125 def order(field, direction = :asc) order_by(field => direction) end |
#order_by(*fields) ⇒ Object
ORDER BY
111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/dorm/query_builder.rb', line 111 def order_by(*fields) clone.tap do |query| formatted_fields = fields.map do |field| case field when Hash field.map { |f, direction| "#{format_field(f)} #{direction.to_s.upcase}" }.join(", ") else format_field(field) end end query.instance_variable_set(:@order_by_fields, formatted_fields) end end |
#page(page_num, per_page = 20) ⇒ Object
Pagination helpers
143 144 145 146 |
# File 'lib/dorm/query_builder.rb', line 143 def page(page_num, per_page = 20) offset_count = (page_num - 1) * per_page limit(per_page).offset(offset_count) end |
#right_join(table, condition = nil, **kwargs) ⇒ Object
85 86 87 |
# File 'lib/dorm/query_builder.rb', line 85 def right_join(table, condition = nil, **kwargs) add_join("RIGHT JOIN", table, condition, kwargs) end |
#select(*fields) ⇒ Object
SELECT methods
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/dorm/query_builder.rb', line 23 def select(*fields) clone.tap do |query| if fields.empty? query.instance_variable_set(:@select_fields, ["#{table_name}.*"]) else formatted_fields = fields.map do |field| case field when Symbol "#{table_name}.#{field}" when String field.include?(".") ? field : "#{table_name}.#{field}" else field.to_s end end query.instance_variable_set(:@select_fields, formatted_fields) end end end |
#select_raw(sql) ⇒ Object
43 44 45 46 47 |
# File 'lib/dorm/query_builder.rb', line 43 def select_raw(sql) clone.tap do |query| query.instance_variable_set(:@select_fields, [sql]) end end |
#sum(field) ⇒ Object
Aggregation methods
194 195 196 197 198 |
# File 'lib/dorm/query_builder.rb', line 194 def sum(field) select_raw("SUM(#{format_field(field)}) as sum") .execute .map { |results| results.first&.[]("sum")&.to_f || 0 } end |
#to_a ⇒ Object
153 154 155 |
# File 'lib/dorm/query_builder.rb', line 153 def to_a execute.value_or([]) end |
#to_sql ⇒ Object
Execution methods
149 150 151 |
# File 'lib/dorm/query_builder.rb', line 149 def to_sql build_sql end |
#where(conditions = nil, **kwargs, &block) ⇒ Object
WHERE methods
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/dorm/query_builder.rb', line 50 def where(conditions = nil, **kwargs, &block) clone.tap do |query| if block_given? # DSL block: where { name.eq("Alice").and(age.gt(18)) } dsl = WhereDSL.new(table_name, query.instance_variable_get(:@param_counter)) condition = dsl.instance_eval(&block) query.instance_variable_get(:@where_conditions) << [condition.to_sql, condition.params] query.instance_variable_set(:@param_counter, query.instance_variable_get(:@param_counter) + condition.params.length) elsif conditions.is_a?(Hash) || !kwargs.empty? # Hash conditions: where(name: "Alice", age: 25) hash_conditions = conditions.is_a?(Hash) ? conditions : kwargs query.add_hash_conditions(hash_conditions) elsif conditions.is_a?(String) # Raw SQL: where("name = ? AND age > ?", "Alice", 18) query.add_where_condition(conditions, []) end end end |
#where_raw(sql, *params) ⇒ Object
70 71 72 73 74 |
# File 'lib/dorm/query_builder.rb', line 70 def where_raw(sql, *params) clone.tap do |query| query.add_where_condition(sql, params) end end |