Module: SimpleMaster::Master::Editable

Extended by:
ActiveSupport::Concern
Defined in:
lib/simple_master/master/editable.rb

Overview

Provide save! helpers for test data

Constant Summary collapse

@@generated_id =

Use a generator that avoids ID collisions across classes

0

Instance Method Summary collapse

Instance Method Details

#current_and_super_classes_each {|klass| ... } ⇒ Object

Yields:

  • (klass)


116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/simple_master/master/editable.rb', line 116

def current_and_super_classes_each
  klass = self.class
  yield klass

  loop do
    klass = klass.superclass
    break unless klass < Master
    next if klass.abstract_class?

    yield klass
  end
end

#destroyObject



141
142
143
144
# File 'lib/simple_master/master/editable.rb', line 141

def destroy
  destroy!
  true
end

#destroy!Object



146
147
148
# File 'lib/simple_master/master/editable.rb', line 146

def destroy!
  fail "Destroy is not allowed"
end

#dirty!Object



18
19
20
# File 'lib/simple_master/master/editable.rb', line 18

def dirty!
  @dirty = true
end

#freezeObject

NOTE: no freezing



151
152
# File 'lib/simple_master/master/editable.rb', line 151

def freeze
end

#generate_idObject

rubocop:disable Style/ClassVars



44
45
46
47
48
49
50
# File 'lib/simple_master/master/editable.rb', line 44

def generate_id
  loop do
    @@generated_id += 1 # rubocop:disable Style/ClassVars
    break unless self.class.base_class.id_hash.key?(@@generated_id)
  end
  @@generated_id
end

#has_changes_to_save?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/simple_master/master/editable.rb', line 26

def has_changes_to_save?
  !@dirty.nil?
end

#new_record?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/simple_master/master/editable.rb', line 22

def new_record?
  id.nil? || self.class.id_hash[id] != self
end

#record_to_saveObject



30
31
32
33
34
35
36
# File 'lib/simple_master/master/editable.rb', line 30

def record_to_save
  # Assumes type_not_match? has already been checked
  return nil if type.nil?
  return @record_to_save if @record_to_save && @record_to_save.type == type

  @record_to_save = type.constantize.new
end

#save(**_options) ⇒ Object

FOR TEST



53
54
55
# File 'lib/simple_master/master/editable.rb', line 53

def save(**_options)
  save!
end

#save!(**_options) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
111
112
113
114
# File 'lib/simple_master/master/editable.rb', line 57

def save!(**_options)
  return if @saving
  @saving = true
  if id.nil?
    self.id = generate_id
  end

  # Save belongs_to.
  association_records = belongs_to_store.dup
  association_records.each do |association_name, record|
    next unless record

    unless send(:"_#{association_name}_target_save?")
      belongs_to_store.delete(association_name)
      next
    end

    record.save
    send(:"#{association_name}=", record)
    belongs_to_store.delete(association_name) if record.is_a?(SimpleMaster::Master)
  end

  if @dirty
    # Update this table
    if type_not_match?
      # If data would be created on the parent class, discard that instance and save separately
      record_to_save&.update!(attributes)
    else
      if new_record?
        id_updated = true
        current_and_super_classes_each { |klass| klass.master_storage.update(id, self) }
        SimpleMaster.logger.debug { "[SimpleMaster] Created: #{self.class}##{id}" }
      else
        current_and_super_classes_each { |klass| klass.master_storage.record_updated }
        SimpleMaster.logger.debug { "[SimpleMaster] Updated: #{self.class}##{id}" }
      end
    end
    @dirty = false
  end

  # save has_many
  association_records = has_many_store.dup

  association_records.each do |association_name, records|
    association = (self.class.all_has_many_associations | self.class.all_has_one_associations).find { |ass| ass.name == association_name }
    records.each do |record|
      if id_updated
        record.send(:"#{association.foreign_key}=", send(association.primary_key))
      end
      record.save
    end
    has_many_store.delete(association_name) if association.target_class < Master
  end

  @saving = false

  self
end

#type_not_match?Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/simple_master/master/editable.rb', line 38

def type_not_match?
  self.class.sti_class? && type != self.class.to_s
end

#update(attributes) ⇒ Object



129
130
131
132
# File 'lib/simple_master/master/editable.rb', line 129

def update(attributes)
  update!(attributes)
  true
end

#update!(attributes) ⇒ Object



134
135
136
137
138
139
# File 'lib/simple_master/master/editable.rb', line 134

def update!(attributes)
  attributes.each do |key, value|
    send :"#{key}=", value
  end
  save!
end