class BazaModels::Query
Attributes
previous_model[RW]
relation[RW]
Public Class Methods
new(args)
click to toggle source
# File lib/baza_models/query.rb, line 10 def initialize(args) @args = args @model = @args[:model] @db = @model.db raise "No database?" unless @db @selects = args[:selects] || [] @wheres = args[:wheres] || [] @includes = args[:includes] || [] @joins = args[:joins] || [] @groups = args[:groups] || [] @offset = args[:offset] @orders = args[:orders] || [] @page = args[:page] @per = args[:per] @previous_model = args[:previous_model] @limit = args[:limit] @joins_tracker = {} end
Public Instance Methods
<<(model)
click to toggle source
# File lib/baza_models/query.rb, line 354 def <<(model) raise "No previous model set" unless @previous_model raise "No relation" unless @relation if model.persisted? model.update_attributes!(@relation.fetch(:foreign_key) => @previous_model.id) else autoloaded_cache_or_create << model end self end
<=(_other)
click to toggle source
# File lib/baza_models/query.rb, line 372 def <=(_other) false end
accessible_by(ability, action = :index)
click to toggle source
CanCan supports
# File lib/baza_models/query.rb, line 368 def accessible_by(ability, action = :index) ability.model_adapter(self, action).database_records end
all()
click to toggle source
# File lib/baza_models/query.rb, line 32 def all self end
any?()
click to toggle source
# File lib/baza_models/query.rb, line 36 def any? if @db.query(clone.select(:id).limit(1).to_sql).fetch true else false end end
average(column_name)
click to toggle source
# File lib/baza_models/query.rb, line 44 def average(column_name) query = select("AVG(#{table_sql}.#{column_sql(column_name)}) AS average") @db.query(query.to_sql).fetch.fetch(:average).to_f end
count()
click to toggle source
# File lib/baza_models/query.rb, line 71 def count if @previous_model&.new_record? autoloaded_cache_or_create.length else query = clone(selects: []) .select("COUNT(*) AS count") .limit(nil) .offset(nil) @db.query(query.to_sql).fetch.fetch(:count) end end
destroy_all()
click to toggle source
# File lib/baza_models/query.rb, line 342 def destroy_all each(&:destroy!) end
each(&blk)
click to toggle source
# File lib/baza_models/query.rb, line 304 def each(&blk) to_enum.each(&blk) end
empty?()
click to toggle source
# File lib/baza_models/query.rb, line 49 def empty? !any? end
find(id)
click to toggle source
# File lib/baza_models/query.rb, line 129 def find(id) model = clone.where(id: id).limit(1).to_enum.first if model model.__send__(:fire_callbacks, :after_find) else raise BazaModels::Errors::RecordNotFound end model end
find_by(args)
click to toggle source
# File lib/baza_models/query.rb, line 141 def find_by(args) clone.where(args).limit(1).to_enum.first end
find_each() { |model| ... }
click to toggle source
# File lib/baza_models/query.rb, line 308 def find_each query = clone query.instance_variable_set(:@order, []) query.instance_variable_set(:@limit, nil) query = query.order(:id) offset = 0 loop do query = query.offset(offset, 1000) offset += 1000 count = 0 query.each do |model| yield model count += 1 end break if count == 0 end end
find_first(args)
click to toggle source
# File lib/baza_models/query.rb, line 330 def find_first(args) clone.where(args).first end
first()
click to toggle source
# File lib/baza_models/query.rb, line 145 def first return autoloaded_cache.first if should_use_autoload? query = clone.limit(1) orders = query.instance_variable_get(:@orders) query = query.order(:id) if orders.empty? query.to_enum.first end
group(name)
click to toggle source
# File lib/baza_models/query.rb, line 248 def group(name) if name.is_a?(Symbol) clone(groups: @groups + ["`#{@model.table_name}`.`#{name}`"]) elsif name.is_a?(String) clone(groups: @groups + [name]) else raise "Didn't know how to group by that argument: #{name}" end end
ids()
click to toggle source
# File lib/baza_models/query.rb, line 53 def ids pluck(:id) end
includes(*names)
click to toggle source
# File lib/baza_models/query.rb, line 185 def includes(*names) clone(includes: @includes + names) end
inspect()
click to toggle source
# File lib/baza_models/query.rb, line 350 def inspect to_s end
joins(*arguments)
click to toggle source
# File lib/baza_models/query.rb, line 236 def joins(*arguments) BazaModels::Query::Inspector.new( query: self, model: @model, argument: arguments, joins: @joins, joins_tracker: @joins_tracker ).execute self end
last()
click to toggle source
# File lib/baza_models/query.rb, line 156 def last return autoloaded_cache.last if should_use_autoload? query = clone.limit(1) orders = query.instance_variable_get(:@orders) query = query.order(:id) if orders.empty? query.reverse_order.to_enum.first end
length()
click to toggle source
# File lib/baza_models/query.rb, line 85 def length if @previous_model && !any_wheres_other_than_relation? && @previous_model.autoloads[@relation.fetch(:relation_name)] @previous_model.autoloads[@relation.fetch(:relation_name)].length else count end end
limit(limit)
click to toggle source
# File lib/baza_models/query.rb, line 181 def limit(limit) clone(limit: limit) end
map(&blk)
click to toggle source
# File lib/baza_models/query.rb, line 273 def map(&blk) to_enum.map(&blk) end
maximum(column_name)
click to toggle source
# File lib/baza_models/query.rb, line 57 def maximum(column_name) query = select("MAX(#{table_sql}.#{column_sql(column_name)}) AS maximum") @db.query(query.to_sql).fetch.fetch(:maximum).to_f end
minimum(column_name)
click to toggle source
# File lib/baza_models/query.rb, line 62 def minimum(column_name) query = select("MIN(#{table_sql}.#{column_sql(column_name)}) AS minimum") @db.query(query.to_sql).fetch.fetch(:minimum).to_f end
new(attributes)
click to toggle source
# File lib/baza_models/query.rb, line 118 def new(attributes) raise "No previous model" unless @previous_model raise "No relation" unless @relation new_sub_model = @model.new(@relation.fetch(:foreign_key) => @previous_model.id) new_sub_model.assign_attributes(attributes) autoloaded_cache_or_create << new_sub_model new_sub_model end
none?()
click to toggle source
# File lib/baza_models/query.rb, line 67 def none? !any? end
offset(offset)
click to toggle source
# File lib/baza_models/query.rb, line 177 def offset(offset) clone(offset: offset) end
order(name)
click to toggle source
# File lib/baza_models/query.rb, line 258 def order(name) if name.is_a?(Symbol) clone(orders: @orders + ["`#{@model.table_name}`.`#{name}`"]) elsif name.is_a?(String) clone(orders: @orders + [name]) else raise "Didn't know how to order by that argument: #{name}" end end
pluck(*column_names)
click to toggle source
# File lib/baza_models/query.rb, line 98 def pluck(*column_names) results = @db.query(select(column_names).to_sql).to_a results.map do |result| if column_names.length == 1 result.fetch(column_names.first) else new_result = [] column_names.each do |column_name| new_result << result.fetch(column_name) end new_result end end end
ransack(params, args = {})
click to toggle source
# File lib/baza_models/query.rb, line 382 def ransack(params, args = {}) BazaModels::Ransacker.new(class: @model, params: params, query: self, args: args) end
reverse_order()
click to toggle source
# File lib/baza_models/query.rb, line 268 def reverse_order @reverse_order = true self end
sanitize_sql(value)
click to toggle source
# File lib/baza_models/query.rb, line 376 def sanitize_sql(value) return value if value.is_a?(Array) || value.is_a?(Integer) || value.is_a?(Integer) "'#{@db.esc(value)}'" end
select(select = nil, &blk)
click to toggle source
# File lib/baza_models/query.rb, line 167 def select(select = nil, &blk) if !select && blk to_enum.select(&blk) elsif select.is_a?(Symbol) clone(selects: @selects + ["`#{@model.table_name}`.`#{select}`"]) else clone(selects: @selects + [select]) end end
size()
click to toggle source
# File lib/baza_models/query.rb, line 93 def size # TODO: This should also take counter caching into account length end
sum(column_name)
click to toggle source
# File lib/baza_models/query.rb, line 113 def sum(column_name) query = select("SUM(#{table_sql}.#{column_sql(column_name)}) AS sum") @db.query(query.to_sql).fetch.fetch(:sum).to_f end
to_a()
click to toggle source
# File lib/baza_models/query.rb, line 334 def to_a to_enum.to_a end
to_enum()
click to toggle source
# File lib/baza_models/query.rb, line 277 def to_enum return autoloaded_cache if should_use_autoload? array_enum = ArrayEnumerator.new do |yielder| @db.query(to_sql).each do |data| yielder << @model.new(data, init: true) end end if @includes.empty? array_enum else array = array_enum.to_a if @includes.any? && array.any? autoloader = BazaModels::Autoloader.new( models: array, autoloads: @includes, db: @db ) autoloader.autoload end array end end
to_s()
click to toggle source
# File lib/baza_models/query.rb, line 346 def to_s "#<BazaModels::Query class=#{@model.name} wheres=#{@wheres}>" end
to_sql()
click to toggle source
# File lib/baza_models/query.rb, line 338 def to_sql BazaModels::Query::SqlGenerator.new(query: self).to_sql end
where(*args)
click to toggle source
# File lib/baza_models/query.rb, line 189 def where(*args) first_arg = args.first new_wheres = @wheres.dup if first_arg.is_a?(String) new_where = "(#{args.shift})" args.each do |arg| new_where.sub!("?", @db.quote_value(arg)) end new_wheres << new_where elsif first_arg.is_a?(Array) str = first_arg.shift first_arg.each do |arg| if arg.is_a?(Symbol) arg = "`#{@model.table_name}`.`#{@db.escape_column(arg)}`" elsif arg.is_a?(FalseClass) arg = "0" elsif arg.is_a?(TrueClass) arg = "1" else arg = @db.quote_value(arg) end str.sub!("?", arg) end new_wheres << "(#{str})" elsif first_arg == nil return Not.new(query: self) else first_arg.each do |key, value| if value.is_a?(Hash) value.each do |hash_key, hash_value| new_wheres << "`#{key}`.`#{key_convert(hash_key, hash_value)}` #{value_with_mode(value_convert(hash_value))}" end else new_wheres << "`#{@model.table_name}`.`#{key_convert(key, value)}` #{value_with_mode(value_convert(value))}" end end end clone(wheres: new_wheres) end
Private Instance Methods
any_mods?()
click to toggle source
# File lib/baza_models/query.rb, line 401 def any_mods? @groups.any? || @includes.any? || @orders.any? || @joins.any? || any_wheres_other_than_relation? end
any_wheres_other_than_relation?()
click to toggle source
# File lib/baza_models/query.rb, line 405 def any_wheres_other_than_relation? if @previous_model && @relation && @wheres.length == 1 looks_like = "`#{@relation.fetch(:table_name)}`.`#{@relation.fetch(:foreign_key)}` = #{@previous_model.id}" return false if @wheres.first == looks_like end true end
autoloaded_cache()
click to toggle source
# File lib/baza_models/query.rb, line 397 def autoloaded_cache @previous_model.autoloads.fetch(@relation.fetch(:relation_name)) end
autoloaded_cache_or_create()
click to toggle source
# File lib/baza_models/query.rb, line 392 def autoloaded_cache_or_create @previous_model.autoloads[@relation.fetch(:relation_name)] ||= [] autoloaded_cache end
autoloaded_on_previous_model?()
click to toggle source
# File lib/baza_models/query.rb, line 415 def autoloaded_on_previous_model? return true if @previous_model && @relation && @previous_model.autoloads.include?(@relation.fetch(:relation_name)) false end
clone(args = {})
click to toggle source
# File lib/baza_models/query.rb, line 421 def clone(args = {}) BazaModels::Query.new({ model: @model, selects: @selects, wheres: @wheres, joins: @joins.dup, includes: @includes, groups: @groups, offset: @offset, orders: @orders, page: @page, per: @per, previous_model: @previous_model, limit: @limit }.merge(args)) end
column_sql(column_name)
click to toggle source
# File lib/baza_models/query.rb, line 478 def column_sql(column_name) "#{@db.sep_col}#{@db.escape_column(column_name)}#{@db.sep_col}" end
key_convert(key, value)
click to toggle source
# File lib/baza_models/query.rb, line 438 def key_convert(key, value) return "#{key}_id" if value.is_a?(BazaModels::Model) key end
method_missing(method_name, *args, &blk)
click to toggle source
Calls superclass method
# File lib/baza_models/query.rb, line 482 def method_missing(method_name, *args, &blk) return super unless @model scopes = @model.instance_variable_get(:@scopes) return super if !scopes || !scopes.key?(method_name) block = scopes.fetch(method_name).fetch(:blk) instance_exec(*args, &block) end
should_use_autoload?()
click to toggle source
# File lib/baza_models/query.rb, line 388 def should_use_autoload? !any_mods? && autoloaded_on_previous_model? end
table_sql()
click to toggle source
# File lib/baza_models/query.rb, line 474 def table_sql @table_sql ||= "#{@db.sep_table}#{@db.escape_table(@model.table_name)}#{@db.sep_table}" end
value_convert(value)
click to toggle source
# File lib/baza_models/query.rb, line 444 def value_convert(value) return value.id if value.is_a?(BazaModels::Model) value end
value_with_mode(value)
click to toggle source
# File lib/baza_models/query.rb, line 450 def value_with_mode(value) if value.is_a?(Array) sql = "IN (" first = true value.each do |val_i| if first first = false else sql << ", " unless first end sql << @db.quote_value(val_i) end sql << ")" sql elsif value == nil "IS NULL" else "= #{@db.quote_value(value)}" end end