Class: Tina4::FakeData
- Inherits:
-
Object
- Object
- Tina4::FakeData
- Defined in:
- lib/tina4/seeder.rb
Overview
Zero-dependency fake data generator with deterministic seeding. Uses Ruby’s built-in Random for reproducible data generation.
Constant Summary collapse
- FIRST_NAMES =
%w[ James Mary Robert Patricia John Jennifer Michael Linda David Elizabeth William Barbara Richard Susan Joseph Jessica Thomas Sarah Charles Karen Christopher Lisa Daniel Nancy Matthew Betty Anthony Margaret Mark Sandra Donald Ashley Steven Dorothy Paul Kimberly Andrew Emily Joshua Donna Kenneth Michelle Kevin Carol Brian Amanda George Melissa Timothy Deborah Ronald Stephanie Edward Rebecca Jason Sharon Jeffrey Laura Ryan Cynthia Jacob Kathleen Gary Amy Nicholas Angela Eric Shirley Jonathan Anna Stephen Brenda Larry Pamela Justin Emma Scott Nicole Brandon Helen Benjamin Samantha Samuel Katherine Raymond Christine Gregory Debra Frank Rachel Alexander Carolyn Patrick Janet Jack Catherine Andre Aisha Wei Yuki Carlos Fatima Raj Priya Mohammed Sophia Liam Olivia Noah Ava Ethan Mia Lucas Isabella Mason Charlotte Logan Amelia Aiden Harper ].freeze
- LAST_NAMES =
%w[ Smith Johnson Williams Brown Jones Garcia Miller Davis Rodriguez Martinez Hernandez Lopez Gonzalez Wilson Anderson Thomas Taylor Moore Jackson Martin Lee Perez Thompson White Harris Sanchez Clark Ramirez Lewis Robinson Walker Young Allen King Wright Scott Torres Nguyen Hill Flores Green Adams Nelson Baker Hall Rivera Campbell Mitchell Carter Roberts Gomez Phillips Evans Turner Diaz Parker Cruz Edwards Collins Reyes Stewart Morris Morales Murphy Cook Rogers Gutierrez Ortiz Morgan Cooper Peterson Bailey Reed Kelly Howard Ramos Kim Cox Ward Richardson Watson Brooks Chavez Wood James Bennett Gray Mendoza Ruiz Hughes Price Alvarez Castillo Sanders Patel Müller Nakamura Singh Chen Silva Ali Okafor ].freeze
- WORDS =
%w[ the be to of and a in that have it for not on with he as you do at this but his by from they we say her she or an will my one all would there their what so up out if about who get which go me when make can like time no just him know take people into year your good some could them see other than then now look only come its over think also back after use two how our work first well way even new want because any these give day most us great small large every found still between name should home big end along each much both help line turn move thing right same old better point long real system data report order product service customer account payment record total status market world company project team value process business group result information development management quality performance technology support research design program network ].freeze
- CITIES =
[ "New York", "London", "Tokyo", "Paris", "Berlin", "Sydney", "Toronto", "Mumbai", "São Paulo", "Cairo", "Lagos", "Dubai", "Singapore", "Hong Kong", "Seoul", "Mexico City", "Bangkok", "Istanbul", "Moscow", "Rome", "Barcelona", "Amsterdam", "Nairobi", "Cape Town", "Johannesburg", "Buenos Aires", "Lima", "Santiago", "Jakarta", "Manila", "Kuala Lumpur", "Auckland", "Vancouver", "Chicago", "San Francisco", "Los Angeles", "Miami", "Boston", "Seattle", "Denver" ].freeze
- COUNTRIES =
[ "United States", "United Kingdom", "Canada", "Australia", "Germany", "France", "Japan", "Brazil", "India", "South Africa", "Nigeria", "Egypt", "Kenya", "Mexico", "Argentina", "Chile", "Colombia", "Spain", "Italy", "Netherlands", "Sweden", "Norway", "Denmark", "Finland", "Switzerland", "Belgium", "Austria", "New Zealand", "Singapore", "South Korea", "Thailand", "Indonesia", "Philippines", "Vietnam", "Malaysia", "United Arab Emirates", "Saudi Arabia", "Turkey", "Poland" ].freeze
- DOMAINS =
%w[ example.com test.org sample.net demo.io mail.com inbox.org webmail.net company.com corp.io biz.net ].freeze
- STREETS =
%w[Main Oak Pine Maple Cedar Elm Park Lake Hill River Church Market King Queen High].freeze
- STREET_TYPES =
%w[Street Avenue Road Drive Lane Boulevard Way Place].freeze
- COMPANY_WORDS =
%w[Tech Global Apex Nova Core Prime Next Blue Bright Smart Swift Peak Fusion Pulse Vertex].freeze
- COMPANY_SUFFIXES =
%w[Inc Corp Ltd LLC Group Solutions Systems Labs].freeze
- JOB_TITLES =
[ "Software Engineer", "Product Manager", "Designer", "Data Analyst", "DevOps Engineer", "CEO", "CTO", "Sales Manager", "Marketing Lead", "Accountant", "Operations Manager", "QA Engineer", "UX Researcher", "Support Specialist", "HR Manager", "Technical Writer" ].freeze
- CURRENCIES =
%w[USD EUR GBP JPY CAD AUD CHF ZAR INR CNY].freeze
- CREDIT_CARD_PREFIXES =
%w[4111 4242 5500 5105].freeze
Class Method Summary collapse
-
.seed(seed) ⇒ Object
Static factory — create a seeded FakeData instance.
Instance Method Summary collapse
- #address ⇒ Object
- #blob(size: 64) ⇒ Object
- #boolean ⇒ Object
- #choice(items) ⇒ Object
- #city ⇒ Object
- #color_hex ⇒ Object
- #company ⇒ Object
- #country ⇒ Object
-
#credit_card ⇒ Object
Generate a fake credit card number (test numbers only, e.g. 4111…).
- #currency ⇒ Object
- #date(start_year: 2020, end_year: 2026) ⇒ Object
- #datetime(start_year: 2020, end_year: 2026) ⇒ Object
- #email(from_name: nil) ⇒ Object
- #first_name ⇒ Object
-
#for_field(field_def, column_name = nil) ⇒ Object
Generate appropriate data based on field definition and column name.
-
#initialize(seed: nil) ⇒ FakeData
constructor
A new instance of FakeData.
- #integer(min: 0, max: 10_000) ⇒ Object
- #ip_address ⇒ Object
- #job_title ⇒ Object
- #json_data(keys: nil) ⇒ Object
- #last_name ⇒ Object
- #name ⇒ Object
- #numeric(min: 0.0, max: 1000.0, decimals: 2) ⇒ Object
- #paragraph(sentences: 3) ⇒ Object
- #password(length: 16) ⇒ Object
- #phone ⇒ Object
-
#run(count = 1, &block) ⇒ Object
Run a generator block ‘count` times and return the results.
- #sentence(words: 6) ⇒ Object
- #slug(words: 3) ⇒ Object
- #text(max_length: 200) ⇒ Object
- #timestamp(start_year: 2020, end_year: 2026) ⇒ Object
- #url ⇒ Object
- #uuid ⇒ Object
- #word ⇒ Object
- #zip_code ⇒ Object
Constructor Details
#initialize(seed: nil) ⇒ FakeData
Returns a new instance of FakeData.
97 98 99 |
# File 'lib/tina4/seeder.rb', line 97 def initialize(seed: nil) @rng = seed ? Random.new(seed) : Random.new end |
Class Method Details
.seed(seed) ⇒ Object
Static factory — create a seeded FakeData instance.
fake = FakeData.seed(42)
fake.name # deterministic
104 105 106 |
# File 'lib/tina4/seeder.rb', line 104 def self.seed(seed) new(seed: seed) end |
Instance Method Details
#address ⇒ Object
217 218 219 |
# File 'lib/tina4/seeder.rb', line 217 def address "#{@rng.rand(1..9999)} #{STREETS[@rng.rand(STREETS.length)]} #{STREET_TYPES[@rng.rand(STREET_TYPES.length)]}" end |
#blob(size: 64) ⇒ Object
192 193 194 |
# File 'lib/tina4/seeder.rb', line 192 def blob(size: 64) SecureRandom.random_bytes(size) end |
#boolean ⇒ Object
173 174 175 |
# File 'lib/tina4/seeder.rb', line 173 def boolean @rng.rand(2) end |
#choice(items) ⇒ Object
205 206 207 |
# File 'lib/tina4/seeder.rb', line 205 def choice(items) items[@rng.rand(items.length)] end |
#city ⇒ Object
209 210 211 |
# File 'lib/tina4/seeder.rb', line 209 def city CITIES[@rng.rand(CITIES.length)] end |
#color_hex ⇒ Object
251 252 253 |
# File 'lib/tina4/seeder.rb', line 251 def color_hex "#%06x" % @rng.rand(0..0xFFFFFF) end |
#company ⇒ Object
225 226 227 228 229 230 |
# File 'lib/tina4/seeder.rb', line 225 def company w1 = COMPANY_WORDS[@rng.rand(COMPANY_WORDS.length)] w2 = COMPANY_WORDS[@rng.rand(COMPANY_WORDS.length)] suffix = COMPANY_SUFFIXES[@rng.rand(COMPANY_SUFFIXES.length)] "#{w1}#{w2} #{suffix}" end |
#country ⇒ Object
213 214 215 |
# File 'lib/tina4/seeder.rb', line 213 def country COUNTRIES[@rng.rand(COUNTRIES.length)] end |
#credit_card ⇒ Object
Generate a fake credit card number (test numbers only, e.g. 4111…).
245 246 247 248 249 |
# File 'lib/tina4/seeder.rb', line 245 def credit_card prefix = CREDIT_CARD_PREFIXES[@rng.rand(CREDIT_CARD_PREFIXES.length)] rest = Array.new(12) { @rng.rand(0..9) }.join prefix + rest end |
#currency ⇒ Object
236 237 238 |
# File 'lib/tina4/seeder.rb', line 236 def currency CURRENCIES[@rng.rand(CURRENCIES.length)] end |
#date(start_year: 2020, end_year: 2026) ⇒ Object
184 185 186 |
# File 'lib/tina4/seeder.rb', line 184 def date(start_year: 2020, end_year: 2026) datetime(start_year: start_year, end_year: end_year).strftime("%Y-%m-%d") end |
#datetime(start_year: 2020, end_year: 2026) ⇒ Object
177 178 179 180 181 182 |
# File 'lib/tina4/seeder.rb', line 177 def datetime(start_year: 2020, end_year: 2026) start_time = Time.new(start_year, 1, 1) end_time = Time.new(end_year, 12, 31, 23, 59, 59) delta = (end_time - start_time).to_i Time.at(start_time.to_i + @rng.rand(0..delta)) end |
#email(from_name: nil) ⇒ Object
120 121 122 123 124 125 126 127 128 |
# File 'lib/tina4/seeder.rb', line 120 def email(from_name: nil) if from_name local = from_name.downcase.split.join(".") else local = "#{first_name.downcase}.#{last_name.downcase}" end local += @rng.rand(1..999).to_s "#{local}@#{DOMAINS[@rng.rand(DOMAINS.length)]}" end |
#first_name ⇒ Object
108 109 110 |
# File 'lib/tina4/seeder.rb', line 108 def first_name FIRST_NAMES[@rng.rand(FIRST_NAMES.length)] end |
#for_field(field_def, column_name = nil) ⇒ Object
Generate appropriate data based on field definition and column name.
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/tina4/seeder.rb', line 271 def for_field(field_def, column_name = nil) col = (column_name || "").to_s.downcase type = field_def[:type] # Skip auto-increment primary keys return nil if field_def[:primary_key] && field_def[:auto_increment] case type when :integer return integer(min: 18, max: 85) if col.include?("age") return integer(min: 1950, max: 2026) if col.include?("year") return integer(min: 1, max: 100) if col =~ /quantity|qty|count/ return boolean if col =~ /active|enabled|visible|^is_/ return integer(min: 1, max: 10) if col =~ /rating|score/ integer(min: 1, max: 10_000) when :float, :decimal decimals = field_def[:scale] || 2 return numeric(min: 0.01, max: 9999.99, decimals: decimals) if col =~ /price|cost|amount|total|fee/ return numeric(min: 0.0, max: 100.0, decimals: decimals) if col =~ /rate|percent|ratio/ return numeric(min: -90.0, max: 90.0, decimals: 6) if col.include?("lat") return numeric(min: -180.0, max: 180.0, decimals: 6) if col =~ /lon|lng/ numeric(min: 0.0, max: 10_000.0, decimals: decimals) when :date date when :datetime, :timestamp when :boolean boolean when :blob blob when :json json_data when :string, :text max_len = field_def[:length] || 255 val = generate_string_for(col, max_len) val.length > max_len ? val[0...max_len] : val else word end end |
#integer(min: 0, max: 10_000) ⇒ Object
164 165 166 |
# File 'lib/tina4/seeder.rb', line 164 def integer(min: 0, max: 10_000) @rng.rand(min..max) end |
#ip_address ⇒ Object
240 241 242 |
# File 'lib/tina4/seeder.rb', line 240 def ip_address "#{@rng.rand(1..255)}.#{@rng.rand(0..255)}.#{@rng.rand(0..255)}.#{@rng.rand(1..254)}" end |
#job_title ⇒ Object
232 233 234 |
# File 'lib/tina4/seeder.rb', line 232 def job_title JOB_TITLES[@rng.rand(JOB_TITLES.length)] end |
#json_data(keys: nil) ⇒ Object
196 197 198 199 200 201 202 203 |
# File 'lib/tina4/seeder.rb', line 196 def json_data(keys: nil) if keys keys.each_with_object({}) { |k, h| h[k] = word } else n = @rng.rand(2..5) n.times.each_with_object({}) { |_, h| h[word] = word } end end |
#last_name ⇒ Object
112 113 114 |
# File 'lib/tina4/seeder.rb', line 112 def last_name LAST_NAMES[@rng.rand(LAST_NAMES.length)] end |
#name ⇒ Object
116 117 118 |
# File 'lib/tina4/seeder.rb', line 116 def name "#{first_name} #{last_name}" end |
#numeric(min: 0.0, max: 1000.0, decimals: 2) ⇒ Object
168 169 170 171 |
# File 'lib/tina4/seeder.rb', line 168 def numeric(min: 0.0, max: 1000.0, decimals: 2) val = min + @rng.rand * (max - min) val.round(decimals) end |
#paragraph(sentences: 3) ⇒ Object
143 144 145 |
# File 'lib/tina4/seeder.rb', line 143 def paragraph(sentences: 3) Array.new(sentences) { sentence(words: @rng.rand(5..12)) }.join(" ") end |
#password(length: 16) ⇒ Object
260 261 262 263 |
# File 'lib/tina4/seeder.rb', line 260 def password(length: 16) chars = [*"a".."z", *"A".."Z", *"0".."9"] Array.new(length) { chars[@rng.rand(chars.length)] }.join end |
#phone ⇒ Object
130 131 132 133 134 135 |
# File 'lib/tina4/seeder.rb', line 130 def phone area = @rng.rand(200..999) mid = @rng.rand(100..999) tail = @rng.rand(1000..9999) "+1 (#{area}) #{mid}-#{tail}" end |
#run(count = 1, &block) ⇒ Object
Run a generator block ‘count` times and return the results.
266 267 268 |
# File 'lib/tina4/seeder.rb', line 266 def run(count = 1, &block) Array.new(count) { block.call } end |
#sentence(words: 6) ⇒ Object
137 138 139 140 141 |
# File 'lib/tina4/seeder.rb', line 137 def sentence(words: 6) w = Array.new(words) { WORDS[@rng.rand(WORDS.length)] } w[0] = w[0].capitalize "#{w.join(' ')}." end |
#slug(words: 3) ⇒ Object
156 157 158 |
# File 'lib/tina4/seeder.rb', line 156 def slug(words: 3) Array.new(words) { WORDS[@rng.rand(WORDS.length)] }.join("-") end |
#text(max_length: 200) ⇒ Object
147 148 149 150 |
# File 'lib/tina4/seeder.rb', line 147 def text(max_length: 200) t = paragraph(sentences: 2) t.length > max_length ? t[0...max_length] : t end |
#timestamp(start_year: 2020, end_year: 2026) ⇒ Object
188 189 190 |
# File 'lib/tina4/seeder.rb', line 188 def (start_year: 2020, end_year: 2026) datetime(start_year: start_year, end_year: end_year).strftime("%Y-%m-%d %H:%M:%S") end |
#url ⇒ Object
160 161 162 |
# File 'lib/tina4/seeder.rb', line 160 def url "https://#{DOMAINS[@rng.rand(DOMAINS.length)]}/#{slug}" end |
#uuid ⇒ Object
255 256 257 258 |
# File 'lib/tina4/seeder.rb', line 255 def uuid h = Array.new(32) { "0123456789abcdef"[@rng.rand(16)] }.join "#{h[0..7]}-#{h[8..11]}-#{h[12..15]}-#{h[16..19]}-#{h[20..31]}" end |
#word ⇒ Object
152 153 154 |
# File 'lib/tina4/seeder.rb', line 152 def word WORDS[@rng.rand(WORDS.length)] end |
#zip_code ⇒ Object
221 222 223 |
# File 'lib/tina4/seeder.rb', line 221 def zip_code @rng.rand(10_000..99_999).to_s end |