Class: ROM::Relation

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/rom/relation.rb,
lib/rom/version.rb

Overview

Enhanced ROM relation wrapping axiom relation and using injected mapper to load/dump tuples/objects

Examples:


# set up an axiom relation
header = [[:id, Integer], [:name, String]]
data   = [[1, 'John'], [2, 'Jane']]
axiom  = Axiom::Relation.new(header, data)

# provide a simple mapper
class Mapper < Struct.new(:header)
  def load(tuple)
    data = header.map { |attribute|
      [attribute.name, tuple[attribute.name]]
    }
    Hash[data]
  end

  def dump(hash)
    header.each_with_object([]) { |attribute, tuple|
      tuple << hash[attribute.name]
    }
  end
end

# wrap axiom relation with ROM relation
mapper   = Mapper.new(axiom.header)
relation = ROM::Relation.new(axiom, mapper)

# relation is an enumerable and it uses mapper to load/dump tuples/objects
relation.to_a
# => [{:id=>1, :name=>'John'}, {:id=>2, :name=>'Jane'}]

# you can insert/update/delete objects
relation.insert(id: 3, name: 'Piotr').to_a
# => [{:id=>1, :name=>"John"}, {:id=>2, :name=>"Jane"}, {:id=>3, :name=>"Piotr"}]

relation.delete(id: 1, name: 'John').to_a
# => [{:id=>2, :name=>"Jane"}]

Constant Summary collapse

VERSION =
'0.1.1'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.build(relation, mapper) ⇒ Relation

Build a new relation

Parameters:

  • (Axiom::Relation)
  • mapper (Object)

Returns:



57
58
59
# File 'lib/rom/relation.rb', line 57

def self.build(relation, mapper)
  new(mapper.call(relation).optimize, mapper)
end

Instance Method Details

#delete(object) ⇒ Relation

Delete an object from the relation

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.delete(id: 1)
relation.to_a # => [[2]]

Parameters:

  • (Object)

Returns:



144
145
146
# File 'lib/rom/relation.rb', line 144

def delete(object)
  new(relation.delete([mapper.dump(object)]))
end

#drop(offset) ⇒ Relation

Drop objects from the relation by the given offset

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.drop(1).to_a # => [[2]]

Parameters:

  • (Integer)

Returns:



249
250
251
# File 'lib/rom/relation.rb', line 249

def drop(offset)
  new(sorted.drop(offset))
end

#each {|| ... } ⇒ Relation

Iterate over tuples yielded by the wrapped relation

Examples:

mapper = Class.new {
  def load(value)
    value.to_s
  end

  def dump(value)
    value.to_i
  end
}.new

relation = ROM::Relation.new([1, 2, 3], mapper)

relation.each do |value|
  puts value # => '1'
end

Yield Parameters:

  • (Object)

Returns:



85
86
87
88
89
# File 'lib/rom/relation.rb', line 85

def each
  return to_enum unless block_given?
  relation.each { |tuple| yield(mapper.load(tuple)) }
  self
end

#first(limit = 1) ⇒ Relation

Take first n-objects from the relation

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.first.to_a # => [[1]]
relation.first(2).to_a # => [[1], [2]]

Parameters:

  • (Integer)

Returns:



214
215
216
# File 'lib/rom/relation.rb', line 214

def first(limit = 1)
  new(sorted.first(limit))
end

#inject_mapper(mapper) ⇒ Relation

Inject a new mapper into this relation

Examples:


relation = ROM::Relation.new([], mapper)
relation.inject_mapper(new_mapper)

Parameters:

  • a (Object)

    mapper object

Returns:



313
314
315
# File 'lib/rom/relation.rb', line 313

def inject_mapper(mapper)
  new(relation, mapper)
end

#insert(object) ⇒ Relation Also known as: <<

Insert an object into relation

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.insert(id: 3)
relation.to_a # => [[1], [2], [3]]

Parameters:

  • (Object)

Returns:



105
106
107
# File 'lib/rom/relation.rb', line 105

def insert(object)
  new(relation.insert([mapper.dump(object)]))
end

#last(limit = 1) ⇒ Relation

Take last n-objects from the relation

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.last.to_a # => [[2]]
relation.last(2).to_a # => [[1], [2]]

Parameters:

  • limit (Integer) (defaults to: 1)

Returns:



232
233
234
# File 'lib/rom/relation.rb', line 232

def last(limit = 1)
  new(sorted.last(limit))
end

#one(&block) ⇒ Object

Return exactly one object matching criteria or raise an error

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [1]])
relation = ROM::Relation.new(axiom, mapper)

relation.one.to_a # => {id: 1}

Parameters:

  • block (Proc)

    optional block to call in case no tuple is returned

Returns:

  • (Object)

Raises:

  • NoTuplesError if no tuples were returned

  • ManyTuplesError if more than one tuple was returned



290
291
292
293
294
295
296
297
298
299
# File 'lib/rom/relation.rb', line 290

def one(&block)
  block  ||= ->() { raise NoTuplesError }
  tuples   = take(2).to_a

  if tuples.count > 1
    raise ManyTuplesError
  else
    tuples.first || block.call
  end
end

#replace(objects) ⇒ Relation

Replace all objects in the relation with new ones

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.replace([{id: 3}, {id: 4}])
relation.to_a # => [[3], [4]]

Parameters:

  • (Array<Object>)

Returns:



162
163
164
# File 'lib/rom/relation.rb', line 162

def replace(objects)
  new(relation.replace(objects.map(&mapper.method(:dump))))
end

#restrict(*args, &block) ⇒ Relation

Restrict the relation

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.restrict(id: 2).to_a # => [[2]]

Parameters:

  • conditions (Hash)

Returns:



179
180
181
# File 'lib/rom/relation.rb', line 179

def restrict(*args, &block)
  new(relation.restrict(*args, &block))
end

#sort_by(*args, &block) ⇒ Relation

Sort the relation by provided attributes

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[2], [1]])
relation = ROM::Relation.new(axiom, mapper)

relation.sort_by(:id).to_a # => [[1], [2]]

Parameters:

  • (Array<Symbol>)

Returns:



266
267
268
# File 'lib/rom/relation.rb', line 266

def sort_by(*args, &block)
  new(relation.sort_by(*args, &block))
end

#take(limit) ⇒ Relation

Take objects form the relation with provided limit

Examples:

axiom    = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
relation = ROM::Relation.new(axiom, mapper)

relation.take(2).to_a # => [[2]]

Parameters:

  • limit (Integer)

Returns:



196
197
198
# File 'lib/rom/relation.rb', line 196

def take(limit)
  new(sorted.take(limit))
end

#update(object, original_tuple) ⇒ Relation

Update an object

Examples:

data     = [[1, 'John'], [2, 'Jane']]
axiom    = Axiom::Relation.new([[:id, Integer], [:name, String]], data)
relation = ROM::Relation.new(axiom, mapper)

relation.update({id: 2, name: 'Jane Doe'}, {id:2, name: 'Jane'})
relation.to_a # => [[1, 'John'], [2, 'Jane Doe']]

Parameters:

  • (Object)
  • original (Hash)

    attributes

Returns:



126
127
128
# File 'lib/rom/relation.rb', line 126

def update(object, original_tuple)
  new(relation.delete([original_tuple]).insert([mapper.dump(object)]))
end