Class: Ni::Storages::Default

Inherits:
Object
  • Object
show all
Defined in:
lib/ni/storages/default.rb

Constant Summary collapse

METADATA_REPOSITORY_KEY =
'store_state'

Instance Method Summary collapse

Constructor Details

#initialize(context, metadata_repository_klass) ⇒ Default

Returns a new instance of Default.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ni/storages/default.rb', line 6

def initialize(context, )
  @context, @metadata_repository_klass = context, 

  @storages_map = {}

  setup_custom_storages

  if defined?(ActiveRecord) && !skip_default_storages?
    register_storage :active_record_record, {
      match: ActiveRecord::Base,
      store: -> (record) { record.save!; [record.class.name, record.id] },
      fetch: -> (data)   { data.first.constantize.find(data.last) }
    }

    register_storage :active_record_collection, {
      match: -> (value) do 
        value.respond_to?(:each) && 
        value.all? { |element| element.is_a?(ActiveRecord::Base) } &&
        value.all? { |element| element.class == value.first.class }
      end,
      store: -> (records) do
        records.each(&:save!)
        [records.first.class.name] + records.map(&:id)
      end,
      fetch: -> (data) do
        klass = data.shift.constantize
        klass.where(id: data)
      end    
    }
  end

  unless skip_default_storages?
    register_storage :true_value, {
      match: TrueClass,
      store: -> (value)  { nil },
      fetch: -> (data)   { true }
    }

    register_storage :false_value, {
      match: FalseClass,
      store: -> (value)  { nil },
      fetch: -> (data)   { false }
    }

    register_storage :string_value, {
      match: String,
      store: -> (value)  { value },
      fetch: -> (data)   { data  }
    }

    register_storage :integer_value, {
      match: Integer,
      store: -> (value)  { value },
      fetch: -> (data)   { data.to_i }
    }

    register_storage :float_value, {
      match: Float,
      store: -> (value)  { value },
      fetch: -> (data)   { data.to_f }
    }

    register_storage :symbol_value, {
      match: Symbol,
      store: -> (value)  { value },
      fetch: -> (data)   { data.to_sym }
    }

    register_storage :nil_value, {
      match: NilClass,
      store: -> (value)  { nil },
      fetch: -> (data)   { nil }
    }
  end
end

Instance Method Details

#fetchObject



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/ni/storages/default.rb', line 112

def fetch
  fetch_data = @metadata_repository_klass.fetch(@context.system_uid, METADATA_REPOSITORY_KEY)

  fetch_data.each do |name, data|
    next if @context.has_key?(name) # do not restore an existing value. E.g. it can be provided on process launch

    if respond_to?(:"store_#{name}")
      @context.raw_set(name, public_send(:"fetch_#{name}", data[:data]))
    elsif data[:known_storage].present?
      if @storages_map[data[:known_storage].to_sym].present?
        @context.raw_set(name, @storages_map[data[:known_storage].to_sym][:fetch].call(data[:data]))
      else
        raise "Storage is not known"
      end    
    else
      raise "Doesn't know how to fetch #{name}"
    end
  end  
end

#storeObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/ni/storages/default.rb', line 82

def store
  fetch_data = {}

  @context.each do |name, value|
    known_storage, config = @storages_map.find do |storage_name, cfg|
      match = cfg[:match]

      (match.is_a?(Class)  && value.is_a?(match)) ||
      (match.is_a?(String) && value.is_a?(match.constantize)) ||
      (match.is_a?(Proc)   && match.call(value))
    end

    if respond_to?(:"store_#{name}")
      fetch_data[name] = { known_storage: nil, data: public_send(:"store_#{name}", value) }
    elsif known_storage.present?
      known_logic = config[:store]

      if known_logic.is_a?(Proc)  
        fetch_data[name] = { known_storage: known_storage, data: known_logic.call(value) }
      else
        raise "Storage logic type is not supported"
      end    
    else
      raise "Logic for storing #{name} was not defined"  
    end
  end

  @metadata_repository_klass.store(@context.system_uid, METADATA_REPOSITORY_KEY, fetch_data)
end