class FrozenRecord::Scope
Constants
- DISALLOWED_ARRAY_METHODS
Public Class Methods
new(klass)
click to toggle source
# File lib/frozen_record/scope.rb, line 27 def initialize(klass) @klass = klass @where_values = [] @where_not_values = [] @order_values = [] @limit = nil @offset = nil end
Public Instance Methods
==(other)
click to toggle source
# File lib/frozen_record/scope.rb, line 132 def ==(other) self.class === other && comparable_attributes == other.comparable_attributes end
average(attribute)
click to toggle source
# File lib/frozen_record/scope.rb, line 84 def average(attribute) pluck(attribute).sum.to_f / count end
exists?()
click to toggle source
# File lib/frozen_record/scope.rb, line 96 def exists? !empty? end
find(id)
click to toggle source
# File lib/frozen_record/scope.rb, line 40 def find(id) raise RecordNotFound, "Can't lookup record without ID" unless id find_by_id(id) or raise RecordNotFound, "Couldn't find a record with ID = #{id.inspect}" end
find_by(criterias)
click to toggle source
# File lib/frozen_record/scope.rb, line 45 def find_by(criterias) where(criterias).first end
find_by!(criterias)
click to toggle source
# File lib/frozen_record/scope.rb, line 49 def find_by!(criterias) where(criterias).first! end
find_by_id(id)
click to toggle source
# File lib/frozen_record/scope.rb, line 36 def find_by_id(id) matching_records.find { |r| r.id == id } end
first!()
click to toggle source
# File lib/frozen_record/scope.rb, line 53 def first! first or raise RecordNotFound, "No record matched" end
hash()
click to toggle source
# File lib/frozen_record/scope.rb, line 128 def hash comparable_attributes.hash end
ids()
click to toggle source
# File lib/frozen_record/scope.rb, line 76 def ids pluck(primary_key) end
last!()
click to toggle source
# File lib/frozen_record/scope.rb, line 57 def last! last or raise RecordNotFound, "No record matched" end
limit(amount)
click to toggle source
# File lib/frozen_record/scope.rb, line 116 def limit(amount) spawn.limit!(amount) end
maximum(attribute)
click to toggle source
# File lib/frozen_record/scope.rb, line 92 def maximum(attribute) pluck(attribute).max end
minimum(attribute)
click to toggle source
# File lib/frozen_record/scope.rb, line 88 def minimum(attribute) pluck(attribute).min end
offset(amount)
click to toggle source
# File lib/frozen_record/scope.rb, line 120 def offset(amount) spawn.offset!(amount) end
order(*ordering)
click to toggle source
# File lib/frozen_record/scope.rb, line 112 def order(*ordering) spawn.order!(*ordering) end
pluck(*attributes)
click to toggle source
# File lib/frozen_record/scope.rb, line 65 def pluck(*attributes) case attributes.length when 1 to_a.map(&attributes.first.to_sym) when 0 raise NotImplementedError, '`.pluck` without arguments is not supported yet' else to_a.map { |r| attributes.map { |a| r[a] }} end end
respond_to_missing?(method_name, *)
click to toggle source
Calls superclass method
# File lib/frozen_record/scope.rb, line 124 def respond_to_missing?(method_name, *) array_delegable?(method_name) || @klass.respond_to?(method_name) || super end
sum(attribute)
click to toggle source
# File lib/frozen_record/scope.rb, line 80 def sum(attribute) pluck(attribute).sum end
to_a()
click to toggle source
# File lib/frozen_record/scope.rb, line 61 def to_a query_results end
where(criterias = :chain)
click to toggle source
# File lib/frozen_record/scope.rb, line 100 def where(criterias = :chain) if criterias == :chain WhereChain.new(self) else spawn.where!(criterias) end end
where_not(criterias)
click to toggle source
# File lib/frozen_record/scope.rb, line 108 def where_not(criterias) spawn.where_not!(criterias) end
Protected Instance Methods
array_delegable?(method)
click to toggle source
# File lib/frozen_record/scope.rb, line 237 def array_delegable?(method) Array.method_defined?(method) && !DISALLOWED_ARRAY_METHODS.include?(method) end
clear_cache!()
click to toggle source
# File lib/frozen_record/scope.rb, line 161 def clear_cache! @comparable_attributes = nil @results = nil @matches = nil self end
comparable_attributes()
click to toggle source
# File lib/frozen_record/scope.rb, line 139 def comparable_attributes @comparable_attributes ||= { klass: @klass, where_values: @where_values.uniq.sort, where_not_values: @where_not_values.uniq.sort, order_values: @order_values.uniq, limit: @limit, offset: @offset, } end
compare(record_a, record_b)
click to toggle source
# File lib/frozen_record/scope.rb, line 212 def compare(record_a, record_b) @order_values.each do |attr, order| a_value, b_value = record_a.send(attr), record_b.send(attr) cmp = a_value <=> b_value next if cmp == 0 return order == :asc ? cmp : -cmp end 0 end
delegate_to_class(*args, &block)
click to toggle source
# File lib/frozen_record/scope.rb, line 233 def delegate_to_class(*args, &block) scoping { @klass.public_send(*args, &block) } end
limit!(amount)
click to toggle source
# File lib/frozen_record/scope.rb, line 258 def limit!(amount) @limit = amount self end
matching_records()
click to toggle source
# File lib/frozen_record/scope.rb, line 172 def matching_records sort_records(select_records(@klass.load_records)) end
method_missing(method_name, *args, &block)
click to toggle source
Calls superclass method
# File lib/frozen_record/scope.rb, line 222 def method_missing(method_name, *args, &block) if array_delegable?(method_name) to_a.public_send(method_name, *args, &block) elsif @klass.respond_to?(method_name) delegate_to_class(method_name, *args, &block) else super end end
offset!(amount)
click to toggle source
# File lib/frozen_record/scope.rb, line 263 def offset!(amount) @offset = amount self end
order!(*ordering)
click to toggle source
# File lib/frozen_record/scope.rb, line 251 def order!(*ordering) @order_values += ordering.map do |order| order.respond_to?(:to_a) ? order.to_a : [[order, :asc]] end.flatten(1) self end
query_results()
click to toggle source
# File lib/frozen_record/scope.rb, line 168 def query_results slice_records(matching_records) end
scoping() { || ... }
click to toggle source
# File lib/frozen_record/scope.rb, line 150 def scoping previous, @klass.current_scope = @klass.current_scope, self yield ensure @klass.current_scope = previous end
select_records(records)
click to toggle source
# File lib/frozen_record/scope.rb, line 176 def select_records(records) return records if @where_values.empty? && @where_not_values.empty? indices = @klass.index_definitions indexed_where_values, unindexed_where_values = @where_values.partition { |criteria| indices.key?(criteria.first) } unless indexed_where_values.empty? attribute, value = indexed_where_values.shift records = indices[attribute].query(value) indexed_where_values.each do |(attribute, value)| records &= indices[attribute].query(value) end end records.select do |record| unindexed_where_values.all? { |attr, matcher| matcher.match?(record[attr]) } && !@where_not_values.any? { |attr, matcher| matcher.match?(record[attr]) } end end
slice_records(records)
click to toggle source
# File lib/frozen_record/scope.rb, line 204 def slice_records(records) return records unless @limit || @offset first = @offset || 0 last = first + (@limit || records.length) records[first...last] || [] end
sort_records(records)
click to toggle source
# File lib/frozen_record/scope.rb, line 196 def sort_records(records) return records if @order_values.empty? records.sort do |record_a, record_b| compare(record_a, record_b) end end
spawn()
click to toggle source
# File lib/frozen_record/scope.rb, line 157 def spawn clone.clear_cache! end
where!(criterias)
click to toggle source
# File lib/frozen_record/scope.rb, line 241 def where!(criterias) @where_values += criterias.map { |k, v| [k.to_s, Matcher.for(v)] } self end
where_not!(criterias)
click to toggle source
# File lib/frozen_record/scope.rb, line 246 def where_not!(criterias) @where_not_values += criterias.map { |k, v| [k.to_s, Matcher.for(v)] } self end