class Gamefic::Query::Base
Constants
- NEST_REGEXP
Attributes
Public Class Methods
# File lib/gamefic/query/base.rb, line 8 def initialize *args @arguments = args end
Public Instance Methods
Determine whether the specified entity passes the query's arguments.
@return [Boolean]
# File lib/gamefic/query/base.rb, line 86 def accept?(entity) result = true arguments.each do |a| result = if a.is_a?(Symbol) (entity.send(a) != false) elsif a.is_a?(Regexp) !entity.to_s.match(a).nil? elsif a.is_a?(Module) || a.is_a?(Class) entity.is_a?(a) else (entity == a) end break if result == false end result end
Determine whether the query allows ambiguous entity references. If false, actions that use this query will only be valid if the token passed into it resolves to a single entity. If true, actions will accept an array of matching entities instead. Queries are not ambiguous by default (ambiguous? == false).
@return [Boolean]
# File lib/gamefic/query/base.rb, line 19 def ambiguous? false end
Subclasses should override this method with the logic required to collect all entities that exist in the query's context.
@return [Array<Object>]
# File lib/gamefic/query/base.rb, line 27 def context_from(subject) [] end
# File lib/gamefic/query/base.rb, line 52 def include?(subject, object) return false unless accept?(object) result = context_from(subject) result.include?(object) end
A ranking of how precise the query's arguments are.
Query
precision is a factor in calculating Action#rank
.
@return [Integer]
# File lib/gamefic/query/base.rb, line 63 def precision if @precision.nil? @precision = 1 arguments.each { |a| if a.is_a?(Class) @precision += 100 elsif a.is_a?(Gamefic::Entity) @precision += 1000 end } @precision end @precision end
Get a collection of objects that exist in the subject's context and match the provided token. The result is provided as a Matches
object.
@return [Gamefic::Query::Matches]
# File lib/gamefic/query/base.rb, line 35 def resolve(subject, token, continued: false) available = context_from(subject) return Matches.new([], '', token) if available.empty? if continued return Matches.execute(available, token, continued: continued) elsif nested?(token) drill = denest(available, token) drill.keep_if{ |e| accept?(e) } return Matches.new(drill, token, '') unless drill.length != 1 return Matches.new([], '', token) end result = available.select{ |e| e.specified?(token) } result = available.select{ |e| e.specified?(token, fuzzy: true) } if result.empty? result.keep_if{ |e| accept? e } Matches.new(result, (result.empty? ? '' : token), (result.empty? ? token : '')) end
# File lib/gamefic/query/base.rb, line 79 def signature "#{self.class.to_s.split('::').last.downcase}(#{simplify_arguments.join(', ')})" end
Protected Instance Methods
Return an array of the entity's children. If the child is accessible, recursively append its children. The result will NOT include the original entity itself.
@return [Array<Object>]
# File lib/gamefic/query/base.rb, line 110 def subquery_accessible entity return [] if entity.nil? result = [] if entity.accessible? entity.children.each do |c| result.push c result.concat subquery_accessible(c) end end result end
Private Instance Methods
# File lib/gamefic/query/base.rb, line 138 def denest(objects, token) parts = token.split(NEST_REGEXP) current = parts.pop last_result = objects.select { |e| e.specified?(current) } last_result = objects.select { |e| e.specified?(current, fuzzy: true) } if last_result.empty? until parts.empty? current = "#{parts.last} #{current}" result = last_result.select { |e| e.specified?(current) } result = last_result.select { |e| e.specified?(current, fuzzy: true) } if result.empty? break if result.empty? parts.pop last_result = result end return [] if last_result.empty? or last_result.length > 1 return last_result if parts.empty? denest(last_result[0].children, parts.join(' ')) end
# File lib/gamefic/query/base.rb, line 134 def nested?(token) !token.match(NEST_REGEXP).nil? end
# File lib/gamefic/query/base.rb, line 124 def simplify_arguments arguments.map do |a| if a.is_a?(Class) || a.is_a?(Object) a.to_s.split('::').last.downcase else a.to_s.downcase end end end