class ReactiveRecord::ScopeDescription
Keeps track of the details (client side) of a scope. The main point is to provide knowledge of what models the scope is joined with, and the client side filter proc
Attributes
name[R]
Public Class Methods
find(target_model, name)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 20 def self.find(target_model, name) name = name.gsub(/!$/,'') target_model.send "_#{name}_synchromesh_scope_description_" rescue nil end
new(model, name, opts)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 7 def initialize(model, name, opts) sself = self @filter_proc = filter_proc(opts) @name = name model.singleton_class.send(:define_method, "_#{@name}_synchromesh_scope_description_") do sself end @model = model build_joins opts[:joins] end
Public Instance Methods
build_error(path, model, attribute)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 96 def build_error(path, model, attribute) "Could not find joins association '#{model.name}.#{attribute}' "\ "for '#{path}' while processing scope #{@model.name}.#{@name}." end
build_joins(joins_list)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 69 def build_joins(joins_list) if !@filter_proc || joins_list == [] @joins = { all: [] } elsif joins_list.nil? @joins = { @model => [[]], all: [] } elsif joins_list == :all @joins = { all: [[]] } else joins_list = [joins_list] unless joins_list.is_a? Array map_joins_path joins_list end end
collector?()
click to toggle source
# File lib/reactive_record/scope_description.rb, line 31 def collector? @is_collector end
crawl(item, method = nil, *vector)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 101 def crawl(item, method = nil, *vector) if !method && item.is_a?(Collection) item.all elsif !method item elsif item.respond_to? :collect item.collect { |record| crawl(record.send(method), *vector) } else crawl(item.send(method), *vector) end end
filter?()
click to toggle source
# File lib/reactive_record/scope_description.rb, line 27 def filter? @filter_proc.respond_to?(:call) end
filter_proc(opts)
click to toggle source
private methods
# File lib/reactive_record/scope_description.rb, line 61 def filter_proc(opts) return true unless opts.key?(:client) || opts.key?(:select) client_opt = opts[:client] || opts[:select] @is_collector = opts.key?(:select) return client_opt if !client_opt || client_opt.respond_to?(:call) raise 'Scope option :client or :select must be a proc, false, or nil' end
filter_records(related_records, args)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 49 def filter_records(related_records, args) if collector? Set.new(related_records.to_a.instance_exec(*args, &@filter_proc)) else Set.new(related_records.select { |r| r.instance_exec(*args, &@filter_proc) }) end rescue Exception => e raise "Client side scope #{@model}.#{@name} raised error: #{e.message}" end
joins_with?(record)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 35 def joins_with?(record) @joins.detect do |klass, vector| vector.any? && (klass == :all || record.class == klass || record.class < klass) end end
map_joins_path(paths)
click to toggle source
# File lib/reactive_record/scope_description.rb, line 82 def map_joins_path(paths) @joins = Hash.new { |h, k| h[k] = Array.new }.merge(@model => [[]]) paths.each do |path| vector = [] path.split('.').inject(@model) do |model, attribute| association = model.reflect_on_association(attribute) raise build_error(path, model, attribute) unless association vector = [association.inverse_of, *vector] @joins[association.klass] << vector association.klass end end end