Class: JetSet::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/jet_set/session.rb

Instance Method Summary collapse

Constructor Details

#initialize(sequel, mapper, query_parser, entity_builder, dependency_graph) ⇒ Session

Initializes Session object. Parameters:

sequel

Sequel sequel object.

mapper

Sequel rows to Ruby objects mapper.

query_parser

a parser which evaluates JetSet extensions in SQL-expressions.



10
11
12
13
14
15
16
17
18
# File 'lib/jet_set/session.rb', line 10

def initialize(sequel, mapper, query_parser, entity_builder, dependency_graph)
  @sequel = sequel
  @mapper = mapper
  @objects = []
  @query_parser = query_parser
  @entity_builder = entity_builder
  @dependency_graph = dependency_graph
  @mutex = Mutex.new
end

Instance Method Details

#attach(*objects) ⇒ Object

Makes an object to be tracked by the session. Since this moment all related to object changes will be saved on session finalization. Use this method for newly created aggregation roots. No need to use it for new objects that were bound to a root which is already attached. All objects loaded from the database are already under the session tracking. Parameters:

objects

any Ruby objects defined in the mapping.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/jet_set/session.rb', line 81

def attach(*objects)
  to_attach = []
  objects.each do |object|
    if object.is_a? Array
      object.each{|o| to_attach << o}
    else
      to_attach << object
    end
  end

  @mutex.synchronize do
    to_attach.each do |object|
      if object.kind_of?(Entity)
        obj = object
      else
        obj = @entity_builder.create(object)
        obj.validate! if obj.respond_to? :validate!
      end

      @objects << obj
    end
  end
end

#fetch(type, expression, params = {}, &block) ⇒ Object

Fetches root entity using a result of execute method. Parameters:

type

Ruby class of an object to map.

expression

SQL-like query

params

query params

&block

further handling of the result.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/jet_set/session.rb', line 26

def fetch(type, expression, params = {}, &block)
  unless type.is_a? Class
    raise MapperError, 'Parameter "type" should be a Class.'
  end

  query = @query_parser.parse(expression)
  unless query.refers_to?(type)
    raise MapperError, "The query doesn't contain \"AS ENTITY #{type.name.underscore}\" statement."
  end

  rows = @sequel.fetch(query.sql, params).to_a
  if rows.length == 0
    result = nil
  elsif rows.length == 1 && query.returns_single_item?
    result = @mapper.map(type, rows[0], self)
  else
    if query.returns_single_item?
      raise MapperError, "A single row was expected to map but the query returned #{rows.length} rows."
    end

    result = []
    rows.each do |row|
      result << @mapper.map(type, row, self)
    end
  end

  if block_given?
    instance_exec(result, &block)
  end

  result
end

#finalizeObject

Saves all changes of attached objects to the database.

  • Compatible with Hypo::Scope finalize interface,

see Hypo docs at github.com/cylon-v/hypo.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/jet_set/session.rb', line 108

def finalize
  dirty_objects = @objects.select {|object| object.dirty?}
  ordered_objects = @dependency_graph.order(dirty_objects)

  begin
    if ordered_objects.length > 0
      @sequel.transaction do
        ordered_objects.each{|obj| obj.flush(@sequel)}
      end
    end
  ensure
    @mutex.synchronize do
      @objects = []
    end
  end
end

#preload(target, relation, query, params = {}, &block) ⇒ Object

Loads nested references and collections using sub-query for previously loaded aggregation root, see map method. Parameters:

target

single or multiple entities that are a Ruby objects constructed by map or preload method.

relation

an object reference or collection name defined in JetSet mapping for the target.



64
65
66
67
68
69
70
71
72
# File 'lib/jet_set/session.rb', line 64

def preload(target, relation, query, params = {}, &block)
  query = @query_parser.parse(query)
  rows = @sequel.fetch(query.sql, params).to_a
  result = @mapper.map_association(target, relation, rows, self)

  if block_given?
    instance_exec(result[:result], result[:ids], &block)
  end
end