Class: POSLavu::QueryScope

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/poslavu/query_scope.rb

Overview

QueryScope represents a retrievable set of records. You can obtain one by calling POSLavu::Client#table() for the table in question.

Query scopes are chainable. Given an initial scope representing all records in a table, you may further restrict the records of interest by with #filter, #page, and #where.

Query scopes are Enumerable. #each is the obvious access method, but #to_a, #map, #inject, and all your friends are also available.

Query scopes are lazy loading. You can manipulate them as much as you want without performing any API calls. The request is actually performed once you call #each or any other Enumerable method. If you’ve called #page, the results are held in memory. If not, #each issues multiple requests (internally paginating) and does not hold the result in memory.

Constant Summary collapse

Operators =

The list of operators supported by the POSLavu API (and thus supported by #filter).

['<=', '>=', '<', '>', '=', '<>', '!=', 'BETWEEN', 'LIKE', 'NOT LIKE']

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#tableObject (readonly)

The name of the table, as passed to POSLavu::Client#table



22
23
24
# File 'lib/poslavu/query_scope.rb', line 22

def table
  @table
end

Instance Method Details

#each(&block) ⇒ Object

Iterate over the records represented by this query scope.

If this scope has an explicit #page set, the results will be retrieved and memoized. Otherwise, this scope will internally paginate and make successive requests, yielding each row in turn, and the results will not be memoized.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/poslavu/query_scope.rb', line 78

def each(&block)
  if @rows
    # we've been memoized
    @rows.each(&block)
    
  elsif start_record
    # we represent a single page
    # do the fetching and iterate
    @rows = fetch_rows

    @rows.each(&block)
  else
    # we represent the whole set of possible records
    # fetch repeatedly, in pages
    page_number = 1
    records_per_page = 100
    
    loop {
      # create a scope for this page
      inner_scope = page(page_number, records_per_page)
      
      # fetch the records as an array
      records = inner_scope.to_a
      
      # pass them to the caller
      records.each(&block)
      
      # is this the last page?
      if records.size < records_per_page
        # was this the first page?
        if page_number == 1
          # this is the only page
          # memoize
          @rows = records
        end
        
        # regardless, we're done
        break
      end
      
      page_number += 1
    }
    
  end
  
  self
end

#filter(field, operator, value, value2 = nil) ⇒ Object

Returns a new QueryScope with the specified filter applied.

The POSLavu API has a basic query language modeled after SQL, probably because they’re shoveling the filter straight into SQL. It supports restricting fields using a set of Operators. All of them require a value for comparison, except BETWEEN, which requires two values.

LIKE and NOT LIKE accept ‘%’ as a wildcard. There is no mechanism for pattern-matching strings containing a percent sign.

Raises:

  • (ArgumentError)


36
37
38
39
40
41
42
43
44
45
# File 'lib/poslavu/query_scope.rb', line 36

def filter(field, operator, value, value2=nil)
  operator = operator.to_s.upcase
  raise ArgumentError, "invalid operator" unless Operators.include?(operator)
  
  chain { |x|
    filter = { 'field' => field, 'operator' => operator, 'value1' => value.to_s }
    filter['value2'] = value2.to_s if operator == 'BETWEEN'
    x.filters << filter
  }
end

#page(number, records_per_page = 40) ⇒ Object

Returns a new QueryScope, restricting results to the specified page number.

Pages are 1-indexed: the first page is page 1, not page 0.

Raises:

  • (ArgumentError)


50
51
52
53
54
55
56
57
# File 'lib/poslavu/query_scope.rb', line 50

def page(number, records_per_page=40)
  raise ArgumentError, "the first page number is 1 (got #{number})" if number < 1
  
  chain { |x|
    x.start_record = (number - 1) * records_per_page
    x.record_count = records_per_page
  }
end

#where(hash) ⇒ Object

Returns a new QueryScope, restricting results to rows matching the specified hash. It is a convenience method around #filter. The following two statements are exactly equivalent:

client.table('orders').where('table_id' => 4, 'no_of_checks' => 2)
client.table('orders').filter('table_id', '=', 4).filter('no_of_checks', '=', 2)


65
66
67
68
69
70
71
# File 'lib/poslavu/query_scope.rb', line 65

def where(hash)
  scope = self
  hash.each { |key,value|
    scope = scope.filter(key, '=', value)
  }
  scope
end