Class: Hold::Sequel::PolymorphicRepository

Inherits:
Object
  • Object
show all
Includes:
IdentitySetRepository
Defined in:
lib/hold/sequel/polymorphic_repository.rb

Overview

Polymorphic repository

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from IdentitySetRepository

#allocates_ids?, #cell, #delete_id, #id_cell, #load, #reload

Methods included from Hold::SetRepository

#contains?, #get_all

Constructor Details

#initialize(db, options = {}) ⇒ PolymorphicRepository

Returns a new instance of PolymorphicRepository.



11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/hold/sequel/polymorphic_repository.rb', line 11

def initialize(db, options = {})
  @db = db
  @table = options[:table] || :base
  @type_column = options[:type_column] || :type
  @id_column = options[:id_column] || :id
  @type_to_model_class_mapping = options[:mapping]
  @model_class_to_type_mapping = @type_to_model_class_mapping.invert

  @repos_for_model_classes = options[:repos] || {}
  @dataset = @db[@table].select(Sequel.as(@type_column, :_type),
                                Sequel.as(@id_column, :_id))
end

Instance Attribute Details

#dbObject (readonly)

Returns the value of attribute db.



7
8
9
# File 'lib/hold/sequel/polymorphic_repository.rb', line 7

def db
  @db
end

#id_columnObject (readonly)

Returns the value of attribute id_column.



7
8
9
# File 'lib/hold/sequel/polymorphic_repository.rb', line 7

def id_column
  @id_column
end

#model_class_to_type_mappingObject (readonly)

Returns the value of attribute model_class_to_type_mapping.



7
8
9
# File 'lib/hold/sequel/polymorphic_repository.rb', line 7

def model_class_to_type_mapping
  @model_class_to_type_mapping
end

#repos_for_model_classesObject (readonly)

Returns the value of attribute repos_for_model_classes.



7
8
9
# File 'lib/hold/sequel/polymorphic_repository.rb', line 7

def repos_for_model_classes
  @repos_for_model_classes
end

#tableObject (readonly)

Returns the value of attribute table.



7
8
9
# File 'lib/hold/sequel/polymorphic_repository.rb', line 7

def table
  @table
end

#type_columnObject (readonly)

Returns the value of attribute type_column.



7
8
9
# File 'lib/hold/sequel/polymorphic_repository.rb', line 7

def type_column
  @type_column
end

#type_to_model_class_mappingObject (readonly)

Returns the value of attribute type_to_model_class_mapping.



7
8
9
# File 'lib/hold/sequel/polymorphic_repository.rb', line 7

def type_to_model_class_mapping
  @type_to_model_class_mapping
end

Instance Method Details

#can_get_class?(model_class) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/hold/sequel/polymorphic_repository.rb', line 24

def can_get_class?(model_class)
  @model_class_to_type_mapping.key?(model_class)
end

#can_set_class?(model_class) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/hold/sequel/polymorphic_repository.rb', line 28

def can_set_class?(model_class)
  @model_class_to_type_mapping.key?(model_class)
end

#construct_entity(property_hash, _row = nil) ⇒ Object



48
49
50
51
# File 'lib/hold/sequel/polymorphic_repository.rb', line 48

def construct_entity(property_hash, _row = nil)
  type = property_hash[:_type] || (fail 'missing _type in result row')
  @type_to_model_class_mapping[type].new(property_hash)
end

#contains_id?(id) ⇒ Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/hold/sequel/polymorphic_repository.rb', line 100

def contains_id?(id)
  !@dataset.filter(@id_column => id).select(1).limit(1).single_value.nil?
end

#delete(object) ⇒ Object



124
125
126
127
# File 'lib/hold/sequel/polymorphic_repository.rb', line 124

def delete(object)
  repo = @repos_for_model_classes[object.class] || (fail StdError)
  repo.delete(object)
end

#get_by_id(id, options = {}) ⇒ Object



91
92
93
# File 'lib/hold/sequel/polymorphic_repository.rb', line 91

def get_by_id(id, options = {})
  get_with_dataset(options) { |ds| ds.filter(@id_column => id) }
end

#get_many_by_ids(ids, options = {}) ⇒ Object



95
96
97
98
# File 'lib/hold/sequel/polymorphic_repository.rb', line 95

def get_many_by_ids(ids, options = {})
  rows = @dataset.filter(@id_column => ids).all
  load_from_rows(rows, options, ids)
end

#get_repo_dependencies_from(repo_set) ⇒ Object



32
33
34
35
36
37
# File 'lib/hold/sequel/polymorphic_repository.rb', line 32

def get_repo_dependencies_from(repo_set)
  @type_to_model_class_mapping.each do |_, model_class|
    @repos_for_model_classes[model_class] ||=
      repo_set.repo_for_model_class(model_class)
  end
end

#get_with_dataset(options = {}) ⇒ Object



85
86
87
88
89
# File 'lib/hold/sequel/polymorphic_repository.rb', line 85

def get_with_dataset(options = {})
  dataset = @dataset
  dataset = yield @dataset if block_given?
  (row = dataset.limit(1).first) && load_from_row(row, options)
end

#load_from_row(row, options = {}) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/hold/sequel/polymorphic_repository.rb', line 77

def load_from_row(row, options = {})
  repo =
    type_to_repo_mapping[row[:_type]] ||
    (fail "PolymorphicRepository: no repo found for type  #{row[:_type]}")

  repo.get_by_id(row[:_id], options)
end

#load_from_rows(rows, options = {}, ids = nil) ⇒ Object

  • Takes multiple result rows with type and id column

  • Groups the IDs by type and does a separate get_many_by_ids query on the relevant repo

  • Combines the results from the separate queries putting them into the order of the IDs from the original rows (or in the order of the ids given, where they are given)



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/hold/sequel/polymorphic_repository.rb', line 63

def load_from_rows(rows, options = {}, ids = nil)
  ids ||= rows.map { |row| row[:_id] }
  ids_by_type = Hash.new { |h, k| h[k] = [] }
  rows.each { |row| ids_by_type[row[:_type]] << row[:_id] }
  results_by_id = {}
  ids_by_type.each do |type, type_ids|
    repo = type_to_repo_mapping[type] ||
           (fail "PolymorphicRepository: no repo found for type #{type}")
    repo.get_many_by_ids(type_ids, options)
      .each_with_index { |res, i| results_by_id[type_ids[i]] = res }
  end
  results_by_id.values_at(*ids)
end

#store(object) ⇒ Object



104
105
106
107
# File 'lib/hold/sequel/polymorphic_repository.rb', line 104

def store(object)
  repo = @repos_for_model_classes[object.class] || (fail StdError)
  repo.store(id, object)
end

#store_new(object) ⇒ Object



109
110
111
112
# File 'lib/hold/sequel/polymorphic_repository.rb', line 109

def store_new(object)
  repo = @repos_for_model_classes[object.class] || (fail StdError)
  repo.store_new(id, object)
end

#transaction(*p, &b) ⇒ Object



53
54
55
# File 'lib/hold/sequel/polymorphic_repository.rb', line 53

def transaction(*p, &b)
  @db.transaction(*p, &b)
end

#type_to_repo_mappingObject



39
40
41
42
43
44
45
46
# File 'lib/hold/sequel/polymorphic_repository.rb', line 39

def type_to_repo_mapping
  @type_to_repo_mapping ||=
    begin
      @type_to_repo_mapping.each_with_obeject({}) do |(t, m), hash|
        hash[t] = @repos_for_model_classes[m]
      end
    end
end

#update(entity, update_entity) ⇒ Object



114
115
116
117
# File 'lib/hold/sequel/polymorphic_repository.rb', line 114

def update(entity, update_entity)
  repo = @repos_for_model_classes[entity.class] || (fail StdError)
  repo.update(entity, update_entity)
end

#update_by_id(id, update_entity) ⇒ Object



119
120
121
122
# File 'lib/hold/sequel/polymorphic_repository.rb', line 119

def update_by_id(id, update_entity)
  repo = @repos_for_model_classes[update_entity.class] || (fail StdError)
  repo.update_by_id(id, update_entity)
end