Class: MasterDataTool::MasterData

Inherits:
Object
  • Object
show all
Defined in:
lib/master_data_tool/master_data.rb

Constant Summary collapse

BULK_INSERT_SIZE =
1000

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(spec_config:, master_data_file:, model_klass:) ⇒ MasterData

Returns a new instance of MasterData.



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/master_data_tool/master_data.rb', line 9

def initialize(spec_config:, master_data_file:, model_klass:)
  @spec_config = spec_config
  @master_data_file = master_data_file
  @model_klass = model_klass

  @loaded = false
  @columns = []
  @new_records = []
  @updated_records = []
  @no_change_records = []
  @deleted_records = []
end

Instance Attribute Details

#columnsObject

Returns the value of attribute columns.



7
8
9
# File 'lib/master_data_tool/master_data.rb', line 7

def columns
  @columns
end

#deleted_recordsObject



93
94
95
96
97
# File 'lib/master_data_tool/master_data.rb', line 93

def deleted_records
  raise MasterDataTool::NotLoadedError unless loaded?

  @deleted_records
end

#master_data_fileObject (readonly)

Returns the value of attribute master_data_file.



7
8
9
# File 'lib/master_data_tool/master_data.rb', line 7

def master_data_file
  @master_data_file
end

#model_klassObject (readonly)

Returns the value of attribute model_klass.



7
8
9
# File 'lib/master_data_tool/master_data.rb', line 7

def model_klass
  @model_klass
end

#new_recordsObject



75
76
77
78
79
# File 'lib/master_data_tool/master_data.rb', line 75

def new_records
  raise MasterDataTool::NotLoadedError unless loaded?

  @new_records
end

#no_change_recordsObject



87
88
89
90
91
# File 'lib/master_data_tool/master_data.rb', line 87

def no_change_records
  raise MasterDataTool::NotLoadedError unless loaded?

  @no_change_records
end

#spec_configObject (readonly)

Returns the value of attribute spec_config.



7
8
9
# File 'lib/master_data_tool/master_data.rb', line 7

def spec_config
  @spec_config
end

#updated_recordsObject



81
82
83
84
85
# File 'lib/master_data_tool/master_data.rb', line 81

def updated_records
  raise MasterDataTool::NotLoadedError unless loaded?

  @updated_records
end

Class Method Details

.build(spec_config:, master_data_file:, load: false) ⇒ Object



23
24
25
26
27
28
# File 'lib/master_data_tool/master_data.rb', line 23

def build(spec_config:, master_data_file:, load: false)
  model_klass = Object.const_get(master_data_file.table_name.classify)
  new(spec_config: spec_config, master_data_file: master_data_file, model_klass: model_klass).tap do |record|
    record.load if load
  end
end

Instance Method Details

#affected?Boolean

Returns:

  • (Boolean)


103
104
105
106
# File 'lib/master_data_tool/master_data.rb', line 103

def affected?
  return @affected if instance_variable_defined?(:@affected)
  @affected = affected_records.any?
end

#affected_recordsObject



71
72
73
# File 'lib/master_data_tool/master_data.rb', line 71

def affected_records
  new_records + updated_records + deleted_records
end

#after_countObject



112
113
114
# File 'lib/master_data_tool/master_data.rb', line 112

def after_count
  @after_count ||= updated_records.count + no_change_records.count + new_records.count
end

#basenameObject



31
32
33
# File 'lib/master_data_tool/master_data.rb', line 31

def basename
  master_data_file.basename
end

#before_countObject



108
109
110
# File 'lib/master_data_tool/master_data.rb', line 108

def before_count
  @before_count ||= updated_records.count + no_change_records.count + deleted_records.count
end

#import!(import_config:, dry_run: true) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/master_data_tool/master_data.rb', line 120

def import!(import_config:, dry_run: true)
  raise MasterDataTool::NotLoadedError unless loaded?

  ignore_foreign_key_when_delete = import_config.ignore_foreign_key_when_delete

  MasterDataTool::Report::ImportReport.new(master_data: self).tap do |report|
    return report if dry_run
    return report unless affected?

    disable_foreign_key_checks if ignore_foreign_key_when_delete
    model_klass.delete_all
    enable_foreign_key_checks if ignore_foreign_key_when_delete

    import_records.each_slice(BULK_INSERT_SIZE) do |chunked_import_records|
      records = chunked_import_records.map { |obj| obj.attributes.slice(*columns) }
      model_klass.insert_all(records)
    end
  end
end

#import_recordsObject



67
68
69
# File 'lib/master_data_tool/master_data.rb', line 67

def import_records
  new_records + updated_records + no_change_records
end

#loadObject



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
# File 'lib/master_data_tool/master_data.rb', line 35

def load
  csv = CSV.read(master_data_file.path, headers: true, skip_blanks: true)
  old_records_by_id = model_klass.all.index_by(&:id)

  csv_records_by_id = build_records_from_csv(csv, old_records_by_id)
  deleted_ids = old_records_by_id.keys - csv_records_by_id.keys

  self.columns = csv.headers

  csv_records_by_id.each do |_, record|
    if record.new_record?
      @new_records << record

      next
    end

    if record.has_changes_to_save?
      @updated_records << record

      next
    end

    @no_change_records << record
  end

  deleted_ids.each do |id|
    @deleted_records << old_records_by_id[id]
  end

  @loaded = true
end

#loaded?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/master_data_tool/master_data.rb', line 99

def loaded?
  @loaded
end


164
165
166
167
168
169
# File 'lib/master_data_tool/master_data.rb', line 164

def print_affected_table
  return unless loaded?
  return unless affected?

  MasterDataTool::Report::PrintAffectedTableReport.new(master_data: self)
end

#table_nameObject



116
117
118
# File 'lib/master_data_tool/master_data.rb', line 116

def table_name
  model_klass.table_name
end

#verify!(verify_config:, ignore_fail: false) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/master_data_tool/master_data.rb', line 140

def verify!(verify_config:, ignore_fail: false)
  MasterDataTool::Report::VerifyReport.new(master_data: self).tap do |report|
    preload_associations = decide_preload_associations(verify_config)
    eager_load_associations = decide_eager_load_associations(verify_config)

    scoped = model_klass.all
    scoped = scoped.preload(preload_associations) unless preload_associations.empty?
    scoped = scoped.eager_load(eager_load_associations) unless eager_load_associations.empty?

    scoped.find_each do |record|
      valid = record.valid?
      report.append(report: MasterDataTool::Report::VerifyReport.build_verify_record_report(master_data: self, record: record, valid: valid))

      next if valid
      next if ignore_fail

      e = MasterDataTool::VerifyFailed.new("[#{table_name}] id = #{record.id} is invalid")
      e.errors = record.errors

      raise e
    end
  end
end