Class: Dynamoid::Criteria::Chain

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/dynamoid/criteria/chain.rb

Overview

The criteria chain is equivalent to an ActiveRecord relation (and realistically I should change the name from chain to relation). It is a chainable object that builds up a query and eventually executes it by a Query or Scan.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ Chain

Create a new criteria chain.

Parameters:

  • source (Class)

    the class upon which the ultimate query will be performed.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/dynamoid/criteria/chain.rb', line 19

def initialize(source)
  @query = {}
  @source = source
  @consistent_read = false
  @scan_index_forward = true

  # Honor STI and :type field if it presents
  type = @source.inheritance_field
  if @source.attributes.key?(type)
    @query[:"#{type}.in"] = @source.deep_subclasses.map(&:name) << @source.name
  end

  # we should re-initialize keys detector every time we change query
  @key_fields_detector = KeyFieldsDetector.new(@query, @source)
end

Instance Attribute Details

#consistent_readObject (readonly)

Returns the value of attribute consistent_read.



13
14
15
# File 'lib/dynamoid/criteria/chain.rb', line 13

def consistent_read
  @consistent_read
end

#key_fields_detectorObject (readonly)

Returns the value of attribute key_fields_detector.



13
14
15
# File 'lib/dynamoid/criteria/chain.rb', line 13

def key_fields_detector
  @key_fields_detector
end

#queryObject (readonly)

Returns the value of attribute query.



13
14
15
# File 'lib/dynamoid/criteria/chain.rb', line 13

def query
  @query
end

#sourceObject (readonly)

Returns the value of attribute source.



13
14
15
# File 'lib/dynamoid/criteria/chain.rb', line 13

def source
  @source
end

Instance Method Details

#allObject

Returns all the records matching the criteria.

Since:

  • 0.2.0



78
79
80
# File 'lib/dynamoid/criteria/chain.rb', line 78

def all
  records
end

#batch(batch_size) ⇒ Object



136
137
138
139
# File 'lib/dynamoid/criteria/chain.rb', line 136

def batch(batch_size)
  @batch_size = batch_size
  self
end

#consistentObject



70
71
72
73
# File 'lib/dynamoid/criteria/chain.rb', line 70

def consistent
  @consistent_read = true
  self
end

#countObject



82
83
84
85
86
87
88
# File 'lib/dynamoid/criteria/chain.rb', line 82

def count
  if @key_fields_detector.key_present?
    count_via_query
  else
    count_via_scan
  end
end

#delete_allObject Also known as: destroy_all

Destroys all the records matching the criteria.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/dynamoid/criteria/chain.rb', line 100

def delete_all
  ids = []
  ranges = []

  if @key_fields_detector.key_present?
    Dynamoid.adapter.query(source.table_name, range_query).flat_map{ |i| i }.collect do |hash|
      ids << hash[source.hash_key.to_sym]
      ranges << hash[source.range_key.to_sym] if source.range_key
    end
  else
    Dynamoid.adapter.scan(source.table_name, scan_query, scan_opts).flat_map{ |i| i }.collect do |hash|
      ids << hash[source.hash_key.to_sym]
      ranges << hash[source.range_key.to_sym] if source.range_key
    end
  end

  Dynamoid.adapter.delete(source.table_name, ids, range_key: ranges.presence)
end

#each(&block) ⇒ Object

Allows you to use the results of a search as an enumerable over the results found.

Since:

  • 0.2.0



154
155
156
# File 'lib/dynamoid/criteria/chain.rb', line 154

def each(&block)
  records.each(&block)
end

#find_by_pages(&block) ⇒ Object



158
159
160
# File 'lib/dynamoid/criteria/chain.rb', line 158

def find_by_pages(&block)
  pages.each(&block)
end

#lastObject

Returns the last fetched record matched the criteria Enumerable doesn’t implement ‘last`, only `first` So we have to implement it ourselves



94
95
96
# File 'lib/dynamoid/criteria/chain.rb', line 94

def last
  all.to_a.last
end

#project(*fields) ⇒ Object



162
163
164
165
# File 'lib/dynamoid/criteria/chain.rb', line 162

def project(*fields)
  @project = fields.map(&:to_sym)
  self
end

#record_limit(limit) ⇒ Object

The record limit is the limit of evaluated records returned by the query or scan.



122
123
124
125
# File 'lib/dynamoid/criteria/chain.rb', line 122

def record_limit(limit)
  @record_limit = limit
  self
end

#scan_index_forward(scan_index_forward) ⇒ Object



146
147
148
149
# File 'lib/dynamoid/criteria/chain.rb', line 146

def scan_index_forward(scan_index_forward)
  @scan_index_forward = scan_index_forward
  self
end

#scan_limit(limit) ⇒ Object

The scan limit which is the limit of records that DynamoDB will internally query or scan. This is different from the record limit as with filtering DynamoDB may look at N scanned records but return 0 records if none pass the filter.



131
132
133
134
# File 'lib/dynamoid/criteria/chain.rb', line 131

def scan_limit(limit)
  @scan_limit = limit
  self
end

#start(start) ⇒ Object



141
142
143
144
# File 'lib/dynamoid/criteria/chain.rb', line 141

def start(start)
  @start = start
  self
end

#where(args) ⇒ Object

The workhorse method of the criteria chain. Each key in the passed in hash will become another criteria that the ultimate query must match. A key can either be a symbol or a string, and should be an attribute name or an attribute name with a range operator.

Examples:

A simple criteria

where(:name => 'Josh')

A more complicated criteria

where(:name => 'Josh', 'created_at.gt' => DateTime.now - 1.day)

Since:

  • 0.2.0



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/dynamoid/criteria/chain.rb', line 46

def where(args)
  detector = IgnoredConditionsDetector.new(args)
  if detector.found?
    Dynamoid.logger.warn(detector.warning_message)
  end

  detector = OverwrittenConditionsDetector.new(@query, args)
  if detector.found?
    Dynamoid.logger.warn(detector.warning_message)
  end

  detector = NonexistentFieldsDetector.new(args, @source)
  if detector.found?
    Dynamoid.logger.warn(detector.warning_message)
  end

  query.update(args.symbolize_keys)

  # we should re-initialize keys detector every time we change query
  @key_fields_detector = KeyFieldsDetector.new(@query, @source)

  self
end