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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8985bb6db2329f6ae7033a3cd2ca2e9f2f1f4af803bf5904fd4e96d8f0f9034e
4
- data.tar.gz: 1fe1d312b363bee756891a16567524d34c845673daa2e2ccb7097d4f1312fc75
3
+ metadata.gz: fe2659cbdd15df894e97db3be809f9040aa3d58f4c1a3df0353e977053e59dca
4
+ data.tar.gz: 9172dafa9ee2f5fab0d51eb0a0eb7c7c127241631c06a9306d5899349ccab83b
5
5
  SHA512:
6
- metadata.gz: 4c55c61b735a271ebac955184ea0e6c7f6207c8be04b87b0ee1e041b5f4f9eb542950204a8756c8f862b4fac94072402333f8357f87c5915c6fd631d06b63457
7
- data.tar.gz: 07ca279207e64e4282a6088acd2c379bef69e5df4bc3ec14960e86fd497d765eb07d00402b4d027b4bc9191b8239a43f52fabe71dccb2ba586da8fbce3523a10
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 105+ countries. Deep
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
@@ -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["#{k}_native"]&.any? } ? %i[latin native] : %i[latin]
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
- .map { |f| File.basename(f, ".yml") }.sort
81
+ .map { |f| File.basename(f, ".yml") }.sort
89
82
  end
90
83
  end
91
84
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NameBank
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.6"
5
5
  end
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 = Class.new(StandardError)
8
- UnknownCountry = Class.new(Error)
9
- UnknownVariant = Class.new(Error)
10
- UnknownScript = Class.new(Error)
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
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
- - !ruby/object:Gem::Dependency
13
- name: rspec
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - "~>"
17
- - !ruby/object:Gem::Version
18
- version: '3.13'
19
- type: :development
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
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 family names for 105+ countries.
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: []