Class: Tarantool::Model::Relation

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
tarantool-model/lib/tarantool/model/relation.rb

Overview

An immutable query over one index condition. The query runs on every enumeration; results are not cached. Order is the index order (descending for :le/:lt); pagination is keyset only, with #after.

Constant Summary collapse

DEFAULTS =
{ index: nil, key: [], iterator: :all, limit: nil, after: nil, filtered: false }.freeze
QUERY =
%i[index key iterator].freeze

Instance Method Summary collapse

Constructor Details

#initialize(model, **options) ⇒ Relation

Returns a new instance of Relation.



13
14
15
16
17
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 13

def initialize(model, **options)
  @model = model
  @options = DEFAULTS.merge(options).freeze
  freeze
end

Instance Method Details

#after(record) ⇒ Object

Raises:

  • (ArgumentError)


29
30
31
32
33
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 29

def after(record)
  raise ArgumentError, "#{record.class.name} has no tuple to continue after" unless record.tuple

  spawn(after: record.tuple)
end

#count(*args, &block) ⇒ Object

Every match of the index condition: limit and after are ignored. With a block or argument, delegates to Enumerable#count (enumerates).



47
48
49
50
51
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 47

def count(*args, &block)
  return @model.verified_storage.count(@model.space_name, **@options.slice(*QUERY)) if args.empty? && !block

  super
end

#each ⇒ Object



35
36
37
38
39
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 35

def each
  return enum_for(:each) unless block_given?

  rows.each { |row| yield @model.instantiate(row) }
end

#find_each(batch_size: 1000, &block) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 53

def find_each(batch_size: 1000, &block)
  return enum_for(:find_each, batch_size:) unless block

  relation = limit(batch_size)

  loop do
    batch = relation.to_a
    batch.each(&block)
    break if batch.size < batch_size

    relation = relation.after(batch.last)
  end
end

#first(count = nil) ⇒ Object



41
42
43
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 41

def first(count = nil)
  count ? limit(count).to_a : limit(1).to_a.first
end

#limit(count) ⇒ Object



25
26
27
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 25

def limit(count)
  spawn(limit: count)
end

#where(index: nil, key: [], iterator: :eq) ⇒ Object

Raises:

  • (ArgumentError)


19
20
21
22
23
# File 'tarantool-model/lib/tarantool/model/relation.rb', line 19

def where(index: nil, key: [], iterator: :eq)
  raise ArgumentError, 'a relation takes one index condition, where was already called' if @options[:filtered]

  spawn(index:, key: Key.wrap(key), iterator:, filtered: true)
end