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 +4 -4
- data/lib/better_seeder/farms/farmer.rb +80 -42
- data/lib/better_seeder/utils/common.rb +69 -0
- data/lib/better_seeder/utils/store.rb +36 -0
- data/lib/better_seeder/version.rb +1 -1
- data/lib/better_seeder.rb +7 -25
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7efa6650656240adf416711cabab9debe997812e5e666472e3391c59ad74ce44
|
4
|
+
data.tar.gz: 504062b646d4800f75dbb20ef7e221fc0da730bf9aa207026795341e9e1c50e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
29
|
+
seed_config = structure_class.respond_to?(:seed_config) ? structure_class.seed_config : {}
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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
|
-
|
106
|
-
|
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
|
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
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
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 |
|
224
|
-
|
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.
|
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-
|
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
|