better_seeder 0.2.3.1 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5b13470c3a8af2c331ef6254593d3268c5a82654802368c4af18608ad629185
4
- data.tar.gz: ba63f74f95445e8b29bab7e33757c9ed460786a655fb9402733b0a7372436086
3
+ metadata.gz: 7efa6650656240adf416711cabab9debe997812e5e666472e3391c59ad74ce44
4
+ data.tar.gz: 504062b646d4800f75dbb20ef7e221fc0da730bf9aa207026795341e9e1c50e3
5
5
  SHA512:
6
- metadata.gz: 8e215fd763c8348003cff4266ba1616eca6e3430e586c754b150ae2f68c97e969c23eec7ad946fd1ba7a1656feb3c507667ef45195834cd531546ea7ecba9e42
7
- data.tar.gz: fc8b41742698a0cd0cf9b3db03a8b57bc2342b528bde096affe737a856f2a329b66063d5130b6b5a618caa1f8c87c169f60064ca4400575514ee1eca4e115feb
6
+ metadata.gz: bc24811f8a5ea605435701ee6ceda23927c1dad77327e054cd9b31756065037ef75a77f6b02bd1c2558f92870746de38366814bea90cd5597aba29a0b85b1e11
7
+ data.tar.gz: 34c2cfc41ca466c7c4e7e4db290a47fc0ffd92503b2fc65c567c716f7123138e2de4f2ce485f4b1c5dc1e56f40f3b8b205b4d96d51deec3da5d35ffc6bc124c0
@@ -6,7 +6,6 @@ module BetterSeeder
6
6
  class << self
7
7
  def generate(options = {})
8
8
  model_name = options[:model] or raise ArgumentError, 'Missing :model option'
9
- count = options[:count] || 10
10
9
 
11
10
  # Costruisce il percorso del file di structure.
12
11
  structure_file = File.expand_path(
@@ -15,7 +14,6 @@ module BetterSeeder
15
14
  )
16
15
  raise "Structure file not found: #{structure_file}" unless File.exist?(structure_file)
17
16
 
18
- # Carica il file di structure.
19
17
  load structure_file
20
18
 
21
19
  # Costruisce il nome della classe di structure: es. "Media::Participant" => "Media::ParticipantStructure"
@@ -28,67 +26,111 @@ module BetterSeeder
28
26
  raise error
29
27
  end
30
28
 
31
- generated_records = []
29
+ seed_config = structure_class.respond_to?(:seed_config) ? structure_class.seed_config : {}
32
30
 
33
- while generated_records.size < count
34
- new_record = nil
35
- loop do
36
- new_record = build_record(model_name, structure_class)
37
- new_record = inject_parent_keys(model_name, new_record, structure_class)
38
- break if validate_record(new_record, structure_class) &&
39
- !record_exists?(model_name, new_record, structure_class, generated_records)
31
+ generated_records = []
32
+ if seed_config.key?(:childs)
33
+ # Logica per il modello child: il numero totale di record = count * childs_count
34
+ parent_count = seed_config[:count] || 10
35
+ childs_count = seed_config.dig(:childs, :count) || 10
36
+
37
+ parent_count.times do |_i|
38
+ childs_count.times do |child_index|
39
+ new_record = nil
40
+ loop do
41
+ # Passo l'indice del record figlio per far variare gli attributi definiti in childs[:attributes]
42
+ new_record = build_record(model_name, structure_class, child_index, child_mode: true)
43
+ new_record = inject_parent_keys(model_name, new_record, structure_class)
44
+ break if validate_record(new_record, structure_class) &&
45
+ !record_exists?(model_name, new_record, structure_class, generated_records)
46
+ end
47
+ generated_records.push(new_record)
48
+ end
49
+ end
50
+ else
51
+ # Logica standard per i modelli parent (o modelli senza childs)
52
+ count = options[:count] || (seed_config[:count] || 10)
53
+ count.times do |index|
54
+ new_record = nil
55
+ loop do
56
+ new_record = build_record(model_name, structure_class, index)
57
+ new_record = inject_parent_keys(model_name, new_record, structure_class)
58
+ break if validate_record(new_record, structure_class) &&
59
+ !record_exists?(model_name, new_record, structure_class, generated_records)
60
+ end
61
+ generated_records.push(new_record)
40
62
  end
41
- generated_records.push(new_record)
42
63
  end
43
64
 
44
65
  generated_records
45
66
  end
46
67
 
68
+ # Il metodo build_record ora supporta la modalità child_mode.
69
+ # Se child_mode è true e nella configurazione (seed_config) è definita la chiave childs con :attributes,
70
+ # per ogni attributo viene usato il valore dell'array corrispondente all'indice (child_index) passato.
71
+ def build_record(_model_name, structure_class, index, child_mode: false)
72
+ generation_rules = structure_class.structure
73
+ raise 'Structure must be a Hash' unless generation_rules.is_a?(Hash)
74
+
75
+ seed_config = structure_class.respond_to?(:seed_config) ? structure_class.seed_config : {}
76
+
77
+ record = {}
78
+ generation_rules.each do |attribute, rule|
79
+ generator = rule[1]
80
+ if child_mode && seed_config.dig(:childs, :attributes, attribute).is_a?(Array)
81
+ values = seed_config[:childs][:attributes][attribute]
82
+ value = values[index] # index viene passato dal loop interno
83
+ else
84
+ value = generator.respond_to?(:call) ? generator.call : generator
85
+ end
86
+ record[attribute] = value
87
+ end
88
+
89
+ record
90
+ end
91
+
92
+ # Restituisce il numero di record figli da generare per ciascun "record padre".
93
+ # Nel caso in cui nella configurazione sia presente la chiave childs, restituisce childs[:count],
94
+ # altrimenti default a 10.
95
+ def child_record_count(options = {})
96
+ model_name = options[:model] or raise ArgumentError, 'Missing :model option'
97
+
98
+ structure_file = File.expand_path(
99
+ File.join(BetterSeeder.configuration.structure_path, "#{model_name.underscore}_structure.rb"),
100
+ Dir.pwd
101
+ )
102
+ raise "Structure file not found: #{structure_file}" unless File.exist?(structure_file)
103
+
104
+ load structure_file
105
+ structure_class_name = "#{model_name}Structure"
106
+ structure_class = Object.const_get(structure_class_name)
107
+ seed_config = structure_class.respond_to?(:seed_config) ? structure_class.seed_config : {}
108
+ seed_config.dig(:childs, :count) || 10
109
+ end
110
+
47
111
  private
48
112
 
49
113
  def record_exists?(_model_name, record, structure_class, generated_records)
50
- # Se non è definito il metodo unique_keys, non eseguiamo il controllo
51
114
  return false unless structure_class.respond_to?(:unique_keys)
52
115
 
53
116
  unique_key_sets = structure_class.unique_keys
54
117
  return false if unique_key_sets.empty?
55
118
 
56
- # Determina il modello associato: si assume che il nome del modello sia
57
- # dato dalla rimozione della stringa "Structure" dal nome della classe di structure.
58
119
  model_class_name = structure_class.to_s.sub(/Structure$/, '')
59
120
  model_class = Object.const_get(model_class_name)
60
121
 
61
- # Per ogni set di chiavi uniche, costruiamo le condizioni della query
62
122
  unique_key_sets.each do |key_set|
63
123
  conditions = {}
64
124
  key_set.each do |col|
65
125
  conditions[col] = record[col]
66
126
  end
67
- # Se esiste un record nel database che soddisfa le condizioni, restituisce true.
68
- return true if generated_records.find do |record|
69
- conditions.all? { |key, value| record[key] == value }
70
- end.present?
127
+ return true if generated_records.find { |r| conditions.all? { |key, value| r[key] == value } }
71
128
  return true if model_class.where(conditions).exists?
72
129
  end
73
130
 
74
131
  false
75
132
  end
76
133
 
77
- def build_record(_model_name, structure_class)
78
- generation_rules = structure_class.structure
79
- raise 'Structure must be a Hash' unless generation_rules.is_a?(Hash)
80
-
81
- record = {}
82
- generation_rules.each do |attribute, rule|
83
- # Ogni rule è un array nel formato [tipo, generatore]
84
- generator = rule[1]
85
- value = generator.respond_to?(:call) ? generator.call : generator
86
- record[attribute] = value
87
- end
88
-
89
- record
90
- end
91
-
92
134
  def inject_parent_keys(_model_name, record, structure_class)
93
135
  config = structure_class.respond_to?(:seed_config) ? structure_class.seed_config : {}
94
136
  parents_spec = config[:parents]
@@ -97,21 +139,17 @@ module BetterSeeder
97
139
  parents_spec.each do |parent_config|
98
140
  parent_model = parent_config[:model]
99
141
  column = parent_config[:column]
142
+ pool_key = parent_model.to_s
100
143
 
101
- # Tenta di ottenere un record del parent dal pool BetterSeeder.generated_records se disponibile.
102
- # Usiamo il nome del modello come chiave nel pool.
103
- pool_key = parent_model.to_s
104
144
  unless defined?(BetterSeeder.generated_records) &&
105
- BetterSeeder.generated_records[pool_key] &&
106
- !BetterSeeder.generated_records[pool_key].empty?
145
+ BetterSeeder.generated_records[pool_key] &&
146
+ !BetterSeeder.generated_records[pool_key].empty?
107
147
  BetterSeeder.generated_records[pool_key] = parent_model.all
108
148
  end
109
- parent_record = BetterSeeder.generated_records[pool_key].sample
110
149
 
150
+ parent_record = BetterSeeder.generated_records[pool_key].sample
111
151
  raise "Parent record not found for #{parent_model}" unless parent_record
112
152
 
113
- # Inietta nel record la chiave esterna indicata nella configurazione.
114
- # binding.pry if model_name == "Media::Participant"
115
153
  record[column] = parent_record[:id]
116
154
  end
117
155
 
@@ -0,0 +1,69 @@
1
+ module BetterSeeder
2
+ module Utils
3
+ module Common
4
+ class << self
5
+
6
+ ##
7
+ # Trasforma un nome di classe in snake_case e aggiunge il suffisso "_structure.rb".
8
+ #
9
+ # ==== Esempio
10
+ # transform_class_name("Campaigns::Campaign")
11
+ # # => "campaigns/campaign_structure.rb"
12
+ #
13
+ # ==== Parametri
14
+ # * +class_name+ - Stringa che rappresenta il nome della classe, eventualmente suddiviso in
15
+ # namespace separati da "::".
16
+ #
17
+ # ==== Ritorno
18
+ # Restituisce una stringa con il nome della classe in formato snake_case e l'ultimo elemento
19
+ # terminato con "_structure.rb".
20
+ #
21
+ def transform_class_name(class_name)
22
+ elements = class_name.split('::').map(&:underscore)
23
+ # Aggiunge "_structure.rb" all'ultimo elemento
24
+ elements[-1] = "#{elements[-1]}_structure.rb"
25
+ elements.join('/')
26
+ end
27
+
28
+ ##
29
+ # Registra un messaggio usando il logger di Rails se disponibile, altrimenti lo stampa su standard output.
30
+ #
31
+ # ==== Parametri
32
+ # * +message+ - Il messaggio da loggare (può essere una stringa o nil).
33
+ #
34
+ # ==== Ritorno
35
+ # Non ritorna un valore significativo.
36
+ #
37
+ def logger(message: nil)
38
+ if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
39
+ Rails.logger.info message
40
+ else
41
+ puts message
42
+ end
43
+ end
44
+
45
+ ##
46
+ # Configura il livello del logger per ActiveRecord in base alla configurazione definita in BetterSeeder.
47
+ #
48
+ # ==== Dettagli
49
+ # Il metodo imposta il livello del logger in base al valore di BetterSeeder.configuration.log_level:
50
+ # * +:debug+ -> Logger::DEBUG
51
+ # * +:info+ -> Logger::INFO
52
+ # * +:error+ -> Logger::ERROR
53
+ # Se il livello non corrisponde a nessuna delle opzioni previste, viene impostato il livello +Logger::DEBUG+.
54
+ #
55
+ def log_level_setup
56
+ level = case BetterSeeder.configuration.log_level
57
+ when :debug then Logger::DEBUG
58
+ when :info then Logger::INFO
59
+ when :error then Logger::ERROR
60
+ else Logger::DEBUG
61
+ end
62
+
63
+ ActiveRecord::Base.logger.level = level
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,36 @@
1
+ # Questo file definisce il modulo +BetterSeeder::Utils::Store+ che offre
2
+ # metodi per memorizzare e recuperare record generati e per gestire la configurazione globale.
3
+ #
4
+ module BetterSeeder
5
+ module Utils
6
+ module Store
7
+ class << self
8
+
9
+ @generated_records = {}
10
+
11
+ ##
12
+ # Restituisce l'hash contenente i record generati.
13
+ #
14
+ # @return [Hash] hash con i record generati per ciascun modello.
15
+ #
16
+ def generated_records
17
+ @generated_records
18
+ end
19
+
20
+ ##
21
+ # Memorizza un record generato per il modello specificato.
22
+ #
23
+ # Se non esiste già, viene inizializzato un array vuoto per il modello.
24
+ #
25
+ # @param model_name [String, Symbol] il nome del modello
26
+ # @param record [Object] il record da memorizzare
27
+ #
28
+ def store_generated_record(model_name, record)
29
+ @generated_records[model_name.to_s] ||= []
30
+ @generated_records[model_name.to_s] << record
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BetterSeeder
4
- VERSION = '0.2.3.1'
4
+ VERSION = '0.2.4'
5
5
  end
data/lib/better_seeder.rb CHANGED
@@ -11,22 +11,6 @@ require_relative 'better_seeder/exporters/sql'
11
11
  require_relative 'better_seeder/builders/structure'
12
12
 
13
13
  module BetterSeeder
14
- class Configuration
15
- attr_accessor :log_language, :structure_path, :preload_path
16
-
17
- def initialize
18
- @log_language = :en
19
- @log_level = :info
20
- if defined?(Rails) && Rails.respond_to?(:root)
21
- @structure_path = Rails.root.join('db', 'seed', 'structure')
22
- @preload_path = Rails.root.join('db', 'seed', 'preload')
23
- else
24
- @structure_path = File.join(Dir.pwd, 'db', 'seed', 'structure')
25
- @preload_path = File.join(Dir.pwd, 'db', 'seed', 'preload')
26
- end
27
- end
28
- end
29
-
30
14
  # Definisce un hash che fungerà da pool per memorizzare i record generati per ciascun modello.
31
15
  @generated_records = {}
32
16
 
@@ -189,14 +173,13 @@ module BetterSeeder
189
173
 
190
174
  # Recupera la classe reale del modello (ActiveRecord).
191
175
  model_class = begin
192
- Object.const_get(model_name)
193
- rescue StandardError
194
- nil
195
- end
176
+ Object.const_get(model_name)
177
+ rescue StandardError
178
+ nil
179
+ end
196
180
  unless model_class
197
181
  message = "[ERROR] Model #{model_name} not found."
198
182
  BetterSeeder::Utils.logger(message: message)
199
-
200
183
  raise Object.const_get(model_name)
201
184
  end
202
185
 
@@ -208,8 +191,7 @@ module BetterSeeder
208
191
  records = Farms::Farmer.generate(model: model_name, count: count)
209
192
  total_records = records.size
210
193
  stats[model_name] = total_records
211
- created_records = load_records_into_db(model_class, records, total_records, model_name,
212
- superclass)
194
+ created_records = load_records_into_db(model_class, records, total_records, model_name, superclass)
213
195
  # Se il modello è parent, salva i record creati per poterli utilizzare in seguito per i modelli child.
214
196
  parent_loaded_records[model_name] = created_records if parent.nil?
215
197
  else
@@ -220,8 +202,8 @@ module BetterSeeder
220
202
  return if BetterSeeder.generated_records[(superclass || model_name).to_s].nil?
221
203
 
222
204
  processed_records = BetterSeeder.generated_records[(superclass || model_name).to_s]
223
- processed_records = processed_records.map do |campaign|
224
- campaign.attributes.except(*excluded_columns.map(&:to_s))
205
+ processed_records = processed_records.map do |record|
206
+ record.attributes.except(*excluded_columns.map(&:to_s))
225
207
  end
226
208
 
227
209
  # Esporta i record nel formato richiesto.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_seeder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3.1
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - alessio_bussolari
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-02-12 00:00:00.000000000 Z
11
+ date: 2025-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-schema
@@ -142,6 +142,8 @@ files:
142
142
  - lib/better_seeder/farms/farmer.rb
143
143
  - lib/better_seeder/structure/utils.rb
144
144
  - lib/better_seeder/utils.rb
145
+ - lib/better_seeder/utils/common.rb
146
+ - lib/better_seeder/utils/store.rb
145
147
  - lib/better_seeder/version.rb
146
148
  - lib/generators/better_seeder/structure_generator.rb
147
149
  homepage: https://github.com/alessiobussolari/better_seeder