Module: Card::Query::Interpretation
- Included in:
- Card::Query
- Defined in:
- lib/card/query/interpretation.rb
Instance Method Summary collapse
- #add_condition(*args) ⇒ Object
- #all_joins ⇒ Object
- #clause_to_hash(clause) ⇒ Object
- #current_conjunction ⇒ Object
-
#interpret(clause) ⇒ Object
normalize and extract meaning from a clause.
- #interpret_attributes(key, val) ⇒ Object
- #interpret_by_key(clause) ⇒ Object
- #normalize_clause(clause) ⇒ Object
- #normalize_string_value(val) ⇒ Object
- #normalize_value(val) ⇒ Object
- #relate(key, val, opts = {}) ⇒ Object
- #relate_compound(key, val) ⇒ Object
- #relate_multi_value(method, key, val) ⇒ Object
Instance Method Details
#add_condition(*args) ⇒ Object
80 81 82 83 84 85 86 87 |
# File 'lib/card/query/interpretation.rb', line 80 def add_condition *args @conditions << if args.size > 1 [args.shift, Value.new(args.shift, self)] else args[0] end end |
#all_joins ⇒ Object
120 121 122 123 |
# File 'lib/card/query/interpretation.rb', line 120 def all_joins @all_joins ||= (joins + subqueries.select(&:unjoined).map(&:all_joins)).flatten end |
#clause_to_hash(clause) ⇒ Object
51 52 53 54 55 56 57 58 |
# File 'lib/card/query/interpretation.rb', line 51 def clause_to_hash clause case clause when Hash then clause when String, Cardname then { key: clause.to_name.key } when Integer then { id: clause } else raise Card::Error::BadQuery, "Invalid query args #{clause.inspect}" end end |
#current_conjunction ⇒ Object
116 117 118 |
# File 'lib/card/query/interpretation.rb', line 116 def current_conjunction @mods[:conj].blank? ? :and : @mods[:conj] end |
#interpret(clause) ⇒ Object
normalize and extract meaning from a clause
6 7 8 |
# File 'lib/card/query/interpretation.rb', line 6 def interpret clause interpret_by_key normalize_clause(clause) end |
#interpret_attributes(key, val) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/card/query/interpretation.rb', line 27 def interpret_attributes key, val case ATTRIBUTES[key] when :basic then add_condition key, val when :conjunction then send key, val when :relational then relate key, val when :special then relate key, val when :ref_relational then relate key, val, method: :join_references when :plus_relational then relate_compound key, val when :ignore then # noop else raise Card::Error::BadQuery, "Invalid attribute #{key}" end end |
#interpret_by_key(clause) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/card/query/interpretation.rb', line 10 def interpret_by_key clause clause.each do |key, val| case when OPERATORS.key?(key.to_s) && !ATTRIBUTES[key] # eg "match" is both operator and attribute; # interpret as attribute when "match" is key interpret content: [key, val] when MODIFIERS.key?(key) && !clause[key].is_a?(Hash) # eg when "sort" is hash, it can have subqueries # and must be interpreted like an attribute @mods[key] = val.is_a?(Array) ? val : val.to_s else interpret_attributes key, val end end end |
#normalize_clause(clause) ⇒ Object
41 42 43 44 45 46 47 48 49 |
# File 'lib/card/query/interpretation.rb', line 41 def normalize_clause clause clause = clause_to_hash clause clause.symbolize_keys! clause.each do |key, val| next if key.to_sym == :return clause[key] = normalize_value val end clause end |
#normalize_string_value(val) ⇒ Object
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/card/query/interpretation.rb', line 69 def normalize_string_value val case val.to_s when /^\$(\w+)$/ # replace from @vars @vars[Regexp.last_match[1].to_sym].to_s.strip when /\b_/ # absolutize based on @context val.to_name.absolute(context) else val end end |
#normalize_value(val) ⇒ Object
60 61 62 63 64 65 66 67 |
# File 'lib/card/query/interpretation.rb', line 60 def normalize_value val case val when Integer, Float, Symbol, Hash then val when String, Cardname then normalize_string_value val when Array then val.map { |v| normalize_value v } else raise Card::Error::BadQuery, "unknown WQL value type: #{val.class}" end end |
#relate(key, val, opts = {}) ⇒ Object
96 97 98 99 100 101 102 103 104 |
# File 'lib/card/query/interpretation.rb', line 96 def relate key, val, opts={} multiple = opts[:multiple].nil? ? val.is_a?(Array) : opts[:multiple] method = opts[:method] || :send if multiple relate_multi_value method, key, val else send method, key, val end end |
#relate_compound(key, val) ⇒ Object
89 90 91 92 93 94 |
# File 'lib/card/query/interpretation.rb', line 89 def relate_compound key, val has_multiple_values = val.is_a?(Array) && (val.first.is_a?(Array) || conjunction(val.first).present?) relate key, val, multiple: has_multiple_values end |
#relate_multi_value(method, key, val) ⇒ Object
106 107 108 109 110 111 112 113 114 |
# File 'lib/card/query/interpretation.rb', line 106 def relate_multi_value method, key, val conj = conjunction(val.first) ? conjunction(val.shift) : :and if conj == current_conjunction # same conjunction as container, no need for subcondition val.each { |v| send method, key, v } else send conj, val.map { |v| { key => v } } end end |