name_bank 0.1.4 → 0.1.6
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/CHANGELOG.md +35 -0
- data/README.md +80 -1
- data/lib/name_bank/pool_schema.rb +24 -0
- data/lib/name_bank/repository.rb +15 -22
- data/lib/name_bank/version.rb +1 -1
- data/lib/name_bank.rb +8 -4
- metadata +21 -35
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fe2659cbdd15df894e97db3be809f9040aa3d58f4c1a3df0353e977053e59dca
|
|
4
|
+
data.tar.gz: 9172dafa9ee2f5fab0d51eb0a0eb7c7c127241631c06a9306d5899349ccab83b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fcbc5f7075593a3da579e91cfaadd1503b976f6457d680b55169d66422826e08e1c6ddc1b37b873444e616a94cf393e4e72524f3f93316dc470c858f0654edbc
|
|
7
|
+
data.tar.gz: 28de093ee1e8e751d6288d659480e240d40755c63a08fa0e59fe4afd23d1ec8e06198634b94bd3f94e9532c086321da90ef9dee10ea2a02a9ba109f2b67b2405
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,41 @@ All notable changes to this project are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
5
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.1.6] - 2026-07-24
|
|
8
|
+
|
|
9
|
+
Tooling and internals only — no API, data or behaviour change.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- RuboCop (with rubocop-rspec, rubocop-rake, rubocop-performance) and
|
|
13
|
+
bundler-audit as development dependencies. The default Rake task now runs
|
|
14
|
+
`spec`, `rubocop` and `bundle:audit:check`.
|
|
15
|
+
- `rake release_check`: the same checks, but refreshing the advisory database
|
|
16
|
+
first. Run before releasing.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- Development dependencies moved from the gemspec to the `:development` group
|
|
20
|
+
in the Gemfile; the gemspec no longer declares any.
|
|
21
|
+
- Internals split for readability: `Repository#names_for_script` extracted from
|
|
22
|
+
`#pool`, and `SplitScripts.split_country` split into `pools`,
|
|
23
|
+
`add_native_pools`, `split_file` and `latin_only`.
|
|
24
|
+
- Specs reorganised — class specs under `spec/name_bank/`, one assertion per
|
|
25
|
+
example.
|
|
26
|
+
|
|
27
|
+
## [0.1.5] - 2026-07-24
|
|
28
|
+
|
|
29
|
+
Metadata and documentation only — no API, data or behaviour change.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- `spec.metadata` in the gemspec: source, changelog, documentation and bug
|
|
33
|
+
tracker links, and `rubygems_mfa_required`.
|
|
34
|
+
- README: "Where it fits" (factory_bot, `db/seeds.rb`, RSpec examples) and
|
|
35
|
+
"Relation to Faker and FFaker" with a comparison table.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- Gem summary and description rewritten so the gem is findable for fake, test
|
|
39
|
+
and seed name data, and states how it relates to Faker and FFaker.
|
|
40
|
+
- README intro says 106 countries (was "105+").
|
|
41
|
+
|
|
7
42
|
## [0.1.4] - 2026-07-24
|
|
8
43
|
|
|
9
44
|
### Added
|
data/README.md
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# name_bank
|
|
2
2
|
|
|
3
|
-
Authentic, gender-matched given and family names for
|
|
3
|
+
Authentic, gender-matched given and family names for 106 countries. Deep
|
|
4
4
|
pools (up to 1500 per country/gender), uniform sampling, deterministic, no
|
|
5
5
|
runtime dependencies.
|
|
6
6
|
|
|
7
|
+
Realistic fake name data for database seeds, factories, fixtures and demo
|
|
8
|
+
environments — a companion to [Faker](https://github.com/faker-ruby/faker) and
|
|
9
|
+
[FFaker](https://github.com/ffaker/ffaker) for the name part.
|
|
10
|
+
|
|
7
11
|
## Installation
|
|
8
12
|
|
|
9
13
|
Add to your Gemfile:
|
|
@@ -42,6 +46,81 @@ Sampling is uniform over each pool and fully deterministic for a given
|
|
|
42
46
|
`rng` — the same seed always yields the same name. `gender:` is `:male`
|
|
43
47
|
or `:female`.
|
|
44
48
|
|
|
49
|
+
## Where it fits
|
|
50
|
+
|
|
51
|
+
A factory_bot factory:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
FactoryBot.define do
|
|
55
|
+
factory :user do
|
|
56
|
+
transient do
|
|
57
|
+
country { "DE" }
|
|
58
|
+
person_gender { :female }
|
|
59
|
+
rng { Random.new }
|
|
60
|
+
person { NameBank.full_name(country: country, gender: person_gender, rng: rng) }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
first_name { person[:firstname] }
|
|
64
|
+
last_name { person[:lastname] }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Database seeds with a fixed seed, so every run produces the same data:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
# db/seeds.rb
|
|
73
|
+
rng = Random.new(20_260_724)
|
|
74
|
+
|
|
75
|
+
%w[DE FR IT ES PL].each do |country|
|
|
76
|
+
100.times do
|
|
77
|
+
person = NameBank.full_name(country: country, gender: [:male, :female].sample(random: rng), rng: rng)
|
|
78
|
+
User.create!(first_name: person[:firstname], last_name: person[:lastname], country: country)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
An RSpec example — the seeded RNG makes the case reproducible:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
it "fits a long Cyrillic name into the invoice header" do
|
|
87
|
+
rng = Random.new(1234)
|
|
88
|
+
customer = NameBank.full_name(country: "RU", gender: :female, rng: rng, script: :native)
|
|
89
|
+
|
|
90
|
+
header = InvoicePdf.new(customer).header
|
|
91
|
+
|
|
92
|
+
expect(header).to include(customer[:lastname])
|
|
93
|
+
end
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Relation to Faker and FFaker
|
|
97
|
+
|
|
98
|
+
Faker and FFaker are full fake-data suites — addresses, companies, lorem ipsum,
|
|
99
|
+
and much more. name_bank does one thing: people names. Use it alongside them,
|
|
100
|
+
not instead of them.
|
|
101
|
+
|
|
102
|
+
| | Faker | FFaker | name_bank |
|
|
103
|
+
| -------------------- | ------------------------------------------------------------ | ------------------------------------------ | ----------------------------------------------------------- |
|
|
104
|
+
| Scope | full fake-data suite | full fake-data suite | people names only |
|
|
105
|
+
| Names addressed by | 58 language/region locales (`de`, `de-AT`, `en-US`) | 30 language modules (`FFaker::NameDE`) | 106 ISO country codes (`DE`, `RU`, `JP`) |
|
|
106
|
+
| Gendered given names | in about 24 of those locales | in 17 of the 30 name modules | in every country |
|
|
107
|
+
| Pool depth | uneven: `en` 1219 m / 4271 f, `de` 574 / 585, `ru` 52 / 56, `ko` 21 | varies per module | up to 1500 per country, gender and script; 89 of 106 at the cap |
|
|
108
|
+
| Native script | one form per locale | one form per module | Latin and native as separate pools, 35 countries |
|
|
109
|
+
| Randomness | global `Faker::Config.random` | global `FFaker::Random.seed` | `rng:` passed in per call, no global state |
|
|
110
|
+
|
|
111
|
+
Counts measured against `faker` and `ffaker` `main` on 2026-07-24.
|
|
112
|
+
|
|
113
|
+
Moving a name call over:
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
Faker::Name.first_name
|
|
117
|
+
FFaker::NameDE.first_name
|
|
118
|
+
# both: gender-agnostic, locale/module picked from global state
|
|
119
|
+
|
|
120
|
+
NameBank.first_name(country: "DE", gender: :female, rng: rng)
|
|
121
|
+
# country and gender explicit, RNG explicit
|
|
122
|
+
```
|
|
123
|
+
|
|
45
124
|
## Scripts
|
|
46
125
|
|
|
47
126
|
Names come in Latin (default) and, for countries with a non-Latin writing
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NameBank
|
|
4
|
+
# The pool-key schema: the base YAML keys, how native-script keys are named,
|
|
5
|
+
# and how a gender maps to its key. Shared by the runtime Repository and the
|
|
6
|
+
# build-time SplitScripts tool so the key names live in one place.
|
|
7
|
+
module PoolSchema
|
|
8
|
+
KEYS = %w[firstnames_male firstnames_female lastnames].freeze
|
|
9
|
+
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def native_key(key)
|
|
13
|
+
"#{key}_native"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def gender_key(gender)
|
|
17
|
+
case gender
|
|
18
|
+
when :male then "firstnames_male"
|
|
19
|
+
when :female then "firstnames_female"
|
|
20
|
+
else raise ArgumentError, "gender must be :male or :female, got #{gender.inspect}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/name_bank/repository.rb
CHANGED
|
@@ -5,8 +5,6 @@ require "yaml"
|
|
|
5
5
|
module NameBank
|
|
6
6
|
# Lazy, memoized loader of per-country name pools stored as YAML in data_dir.
|
|
7
7
|
class Repository
|
|
8
|
-
KEYS = %w[firstnames_male firstnames_female lastnames].freeze
|
|
9
|
-
|
|
10
8
|
def initialize(data_dir:)
|
|
11
9
|
@data_dir = data_dir
|
|
12
10
|
@countries_cache = {}
|
|
@@ -14,7 +12,7 @@ module NameBank
|
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def firstnames(country:, gender:, variant: nil, script: :latin)
|
|
17
|
-
pool(load(country, variant), gender_key(gender), script, country)
|
|
15
|
+
pool(load(country, variant), PoolSchema.gender_key(gender), script, country)
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def lastnames(country:, variant: nil, script: :latin)
|
|
@@ -23,7 +21,7 @@ module NameBank
|
|
|
23
21
|
|
|
24
22
|
def scripts(country:)
|
|
25
23
|
data = load(country, nil)
|
|
26
|
-
KEYS.any? { |k| data[
|
|
24
|
+
PoolSchema::KEYS.any? { |k| data[PoolSchema.native_key(k)]&.any? } ? %i[latin native] : %i[latin]
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
def countries
|
|
@@ -36,29 +34,24 @@ module NameBank
|
|
|
36
34
|
|
|
37
35
|
private
|
|
38
36
|
|
|
39
|
-
def gender_key(gender)
|
|
40
|
-
case gender
|
|
41
|
-
when :male then "firstnames_male"
|
|
42
|
-
when :female then "firstnames_female"
|
|
43
|
-
else raise ArgumentError, "gender must be :male or :female, got #{gender.inspect}"
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
37
|
def pool(data, key, script, country)
|
|
48
|
-
names =
|
|
49
|
-
case script
|
|
50
|
-
when :latin then data.fetch(key)
|
|
51
|
-
when :native
|
|
52
|
-
native = data["#{key}_native"]
|
|
53
|
-
native && !native.empty? ? native : data.fetch(key)
|
|
54
|
-
else
|
|
55
|
-
raise ArgumentError, "script must be :latin or :native, got #{script.inspect}"
|
|
56
|
-
end
|
|
38
|
+
names = names_for_script(data, key, script)
|
|
57
39
|
raise UnknownScript, "#{country}/#{script}" if names.nil? || names.empty?
|
|
58
40
|
|
|
59
41
|
names
|
|
60
42
|
end
|
|
61
43
|
|
|
44
|
+
def names_for_script(data, key, script)
|
|
45
|
+
case script
|
|
46
|
+
when :latin then data.fetch(key)
|
|
47
|
+
when :native
|
|
48
|
+
native = data[PoolSchema.native_key(key)]
|
|
49
|
+
native && !native.empty? ? native : data.fetch(key)
|
|
50
|
+
else
|
|
51
|
+
raise ArgumentError, "script must be :latin or :native, got #{script.inspect}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
62
55
|
def load(country, variant)
|
|
63
56
|
variant ? load_variant(country, variant) : load_country(country)
|
|
64
57
|
end
|
|
@@ -85,7 +78,7 @@ module NameBank
|
|
|
85
78
|
return [] unless Dir.exist?(dir)
|
|
86
79
|
|
|
87
80
|
Dir.children(dir).select { |f| f.end_with?(".yml") }
|
|
88
|
-
|
|
81
|
+
.map { |f| File.basename(f, ".yml") }.sort
|
|
89
82
|
end
|
|
90
83
|
end
|
|
91
84
|
end
|
data/lib/name_bank/version.rb
CHANGED
data/lib/name_bank.rb
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "name_bank/version"
|
|
4
|
+
require_relative "name_bank/pool_schema"
|
|
4
5
|
require_relative "name_bank/repository"
|
|
5
6
|
|
|
7
|
+
# Authentic, gender-matched given names and surnames for 106 countries,
|
|
8
|
+
# addressed by ISO alpha-2 country code. Sampling is uniform and deterministic
|
|
9
|
+
# from a caller-supplied RNG — no global locale or random state.
|
|
6
10
|
module NameBank
|
|
7
|
-
Error
|
|
8
|
-
UnknownCountry
|
|
9
|
-
UnknownVariant
|
|
10
|
-
UnknownScript
|
|
11
|
+
class Error < StandardError; end
|
|
12
|
+
class UnknownCountry < Error; end
|
|
13
|
+
class UnknownVariant < Error; end
|
|
14
|
+
class UnknownScript < Error; end
|
|
11
15
|
|
|
12
16
|
DATA_DIR = File.expand_path("../data", __dir__)
|
|
13
17
|
|
metadata
CHANGED
|
@@ -1,45 +1,24 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: name_bank
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrick Bartels
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
-
dependencies:
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
requirements:
|
|
23
|
-
- - "~>"
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '3.13'
|
|
26
|
-
- !ruby/object:Gem::Dependency
|
|
27
|
-
name: rake
|
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
|
29
|
-
requirements:
|
|
30
|
-
- - "~>"
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '13.0'
|
|
33
|
-
type: :development
|
|
34
|
-
prerelease: false
|
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
-
requirements:
|
|
37
|
-
- - "~>"
|
|
38
|
-
- !ruby/object:Gem::Version
|
|
39
|
-
version: '13.0'
|
|
40
|
-
description: A fast, dependency-free generator of authentic, gender-matched given
|
|
41
|
-
names and surnames for 105+ countries, plus hand-curated pools and cultural variants.
|
|
42
|
-
Uniform, deterministic sampling from a caller-supplied RNG.
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: 'NameBank generates authentic, gender-matched given names and surnames
|
|
13
|
+
for 106 countries, addressed by ISO alpha-2 country code, including native-script
|
|
14
|
+
pools (Cyrillic, Arabic, Han, Hangul, Kana, Greek, Hebrew and more) for 35 of them.
|
|
15
|
+
Pools hold up to 1500 names per country, gender and script. Use it for realistic
|
|
16
|
+
fake name data in database seeds, factory_bot factories, RSpec fixtures, demo and
|
|
17
|
+
staging data. It complements the general-purpose fake data gems Faker and FFaker
|
|
18
|
+
rather than replacing them: keep those for addresses, companies and lorem ipsum,
|
|
19
|
+
and use name_bank where you need per-country, gender-matched people names with deep
|
|
20
|
+
pools. Sampling is uniform and deterministic from a caller-supplied RNG — no global
|
|
21
|
+
locale or random state. No runtime dependencies.'
|
|
43
22
|
executables: []
|
|
44
23
|
extensions: []
|
|
45
24
|
extra_rdoc_files: []
|
|
@@ -157,12 +136,18 @@ files:
|
|
|
157
136
|
- data/variants/US/african_american.yml
|
|
158
137
|
- docs/name-counts.md
|
|
159
138
|
- lib/name_bank.rb
|
|
139
|
+
- lib/name_bank/pool_schema.rb
|
|
160
140
|
- lib/name_bank/repository.rb
|
|
161
141
|
- lib/name_bank/version.rb
|
|
162
142
|
homepage: https://github.com/roughneck/name_bank
|
|
163
143
|
licenses:
|
|
164
144
|
- Apache-2.0
|
|
165
|
-
metadata:
|
|
145
|
+
metadata:
|
|
146
|
+
source_code_uri: https://github.com/roughneck/name_bank
|
|
147
|
+
changelog_uri: https://github.com/roughneck/name_bank/blob/master/CHANGELOG.md
|
|
148
|
+
documentation_uri: https://rubydoc.info/gems/name_bank
|
|
149
|
+
bug_tracker_uri: https://github.com/roughneck/name_bank/issues
|
|
150
|
+
rubygems_mfa_required: 'true'
|
|
166
151
|
rdoc_options: []
|
|
167
152
|
require_paths:
|
|
168
153
|
- lib
|
|
@@ -179,5 +164,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
179
164
|
requirements: []
|
|
180
165
|
rubygems_version: 3.6.9
|
|
181
166
|
specification_version: 4
|
|
182
|
-
summary: Authentic, gender-matched given and
|
|
167
|
+
summary: Authentic, gender-matched given names and surnames for 106 countries — fake
|
|
168
|
+
name data for seeds, factories and tests.
|
|
183
169
|
test_files: []
|