fantasy_faker 0.3.0 → 0.4.0

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: b2564d8293a91c1c0572693b78d0a2d472b9bada33506defd0af70015cb7de5f
4
- data.tar.gz: '00709549331b1fd21196009a36c9baa8d1c1c497868b5a68320e70b8e5562f30'
3
+ metadata.gz: 0f0049ad8d6fbde0f3813c16ade4afca229428ad9ab6754914de5a98ae640114
4
+ data.tar.gz: e66524a426cc3c357511a4537cfbd5b4da7c01b8bb69cd8eda43a07b4c5050c0
5
5
  SHA512:
6
- metadata.gz: dba61364fc29ce55098bc2610f02c5c993faeb348112acbd20b1de42f3a112f60f7fdec2c78d8f3ef4112c7dbd67480fc2d49edfc43622754174fe26dac85acb
7
- data.tar.gz: 6bb6a69246f54fc860840f45e96d80a3d80f52e55dfaf21b775ae036d2d08e57ef2fc9469d6947e9eee5eaa7b5b6ac44c83fce2d83888833790de6b4f2dc7e77
6
+ metadata.gz: a62d8cbbad60bc9bf5b8e0f868b218d42d57d7ced05cdbb36b701cfdfc310d4ae2796cd2f8f0825e5b72f1484a5863757c95310ecbb5f2fc983ee1c8fd86e610
7
+ data.tar.gz: 9b25c3b7dc00ddff98d867aece0bda0274db9469766064bb241922fcf1e184103cef7d028b411e234939e62d423ac2979838b4e41e1137921d5b9e3d136f35de
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 - November 11, 2026
4
+
5
+ - Add `FantasyFaker::Location` with 16 location categories and a general-purpose `.name` generator.
6
+ - Add a shared pool of 1,000 invented location names, with English and Polish landmark templates and dark fantasy prefixes and suffixes.
7
+ - Share location `.unique` history across all categories, `.name`, and locales, reserving the proper name regardless of decorative variants; keep character uniqueness unchanged.
8
+ - Add `FantasyFaker::Location.unique.clear` to reset the shared location history.
9
+
3
10
  ## 0.3.0 - October 24, 2026
4
11
 
5
12
  - Add `.unique` to all character name and nickname generators, with per-method tracking across locale changes.
data/README.md CHANGED
@@ -50,17 +50,65 @@ FantasyFaker.use_locale(:pl) do
50
50
  end
51
51
  ```
52
52
 
53
+ ### Locations
54
+
55
+ `FantasyFaker::Location` uses a shared pool of 1,000 invented proper names across
56
+ 16 categories, with English (`:en`) and Polish (`:pl`) landmark descriptions:
57
+
58
+ Cities return the proper name alone. Other categories combine it with a localized
59
+ landmark type and optional prefixes or suffixes, mixing neutral and dark fantasy styles:
60
+ `Alador Forest`, `Dark Alador Forest`, `Las Alador` or `Puszcza Alador Czarnych Cierni`.
61
+ Proper names are shared between locales; changing language changes the description,
62
+ not the underlying proper-name pool.
63
+
64
+ | Method | Category |
65
+ | --- | --- |
66
+ | `city` | Cities |
67
+ | `sewer` | Urban sewers |
68
+ | `meadow` | Meadows and wetlands |
69
+ | `forest` | Forests |
70
+ | `swamp` | Swamps |
71
+ | `waters` | Rivers and lakes |
72
+ | `desert` | Deserts and dunes |
73
+ | `cave` | Caves |
74
+ | `mine` | Mines |
75
+ | `mountain` | Mountains |
76
+ | `volcanic_field` | Volcanic fields |
77
+ | `ruins` | Ruins |
78
+ | `stronghold` | Strongholds |
79
+ | `graveyard` | Graveyards |
80
+ | `abandoned_monastery` | Abandoned monasteries |
81
+ | `labyrinth_or_arena` | Labyrinths and arenas |
82
+
83
+ Use `name` to choose a random category and generate a name from it:
84
+
85
+ ```ruby
86
+ FantasyFaker::Location.city # => "Alador"
87
+ FantasyFaker::Location.forest # => "Dark Alador Forest"
88
+ FantasyFaker::Location.name # => a name from any location category
89
+
90
+ FantasyFaker.use_locale(:pl) do
91
+ FantasyFaker::Location.city # => "Alador"
92
+ FantasyFaker::Location.forest # => "Mroczny Las Alador"
93
+ FantasyFaker::Location.waters # => "Jezioro Alador Zatopionych Dzwonów"
94
+ end
95
+ ```
96
+
53
97
  ### Unique values
54
98
 
55
- Use `.unique` with any character generator: `male_first_name`, `female_first_name`,
56
- `male_nickname`, `female_nickname`, `male_name`, or `female_name`.
99
+ Use `.unique` with any character or location generator.
57
100
 
58
101
  ```ruby
59
102
  FantasyFaker::Character.unique.male_name
60
103
  FantasyFaker::Character.unique.female_nickname
104
+ FantasyFaker::Location.unique.city
105
+ FantasyFaker::Location.unique.name
61
106
 
62
107
  # Reset all character generators' uniqueness history (for example, between tests)
63
108
  FantasyFaker::Character.unique.clear
109
+
110
+ # Location history is separate from character history
111
+ FantasyFaker::Location.unique.clear
64
112
  ```
65
113
 
66
114
  In FactoryBot (formerly FactoryGirl), use it inside the attribute block:
@@ -69,23 +117,39 @@ In FactoryBot (formerly FactoryGirl), use it inside the attribute block:
69
117
  factory :character do
70
118
  name { FantasyFaker::Character.unique.male_name }
71
119
  end
120
+
121
+ factory :location do
122
+ name { FantasyFaker::Location.unique.forest }
123
+ end
72
124
  ```
73
125
 
74
- Values are tracked separately for each method within the current Ruby process,
75
- including across locale changes. Ordinary calls without `.unique` are not tracked.
76
- This does not check existing database records or coordinate separate processes.
126
+ Character generators track values separately for each method. Location generators share
127
+ one proper-name history across **all categories, `.name`, and both locales**. For example,
128
+ after `.unique.city` returns `Alador`, no other unique location generator can return
129
+ `Las Alador`, `Dark Alador Forest` or any other variant containing that proper name.
130
+ Prefixes and suffixes do not count as new proper names.
131
+
132
+ Character and location histories are separate. Ordinary calls without `.unique` are not
133
+ tracked and can still reuse names. Tracking happens within the current Ruby process;
134
+ it does not check existing database records or coordinate separate processes.
77
135
 
78
136
  If no new value is found after 10,000 attempts, generation raises
79
137
  `FantasyFaker::UniqueGenerator::RetryLimitExceeded` rather than returning a duplicate.
80
138
  Because generation is random, this can happen before every possible value has been used.
139
+ The shared location pool contains 1,000 proper names in total, not 1,000 per category
140
+ or language. Use `FantasyFaker::Location.unique.clear` between tests when names can be reused;
141
+ this resets the history for all location categories at once.
81
142
 
82
143
  ## Development
83
144
 
84
145
  Dictionary data is stored in YAML files under `locales/`:
85
- - `locales/common.yml`: language-independent lists (e.g. name prefixes and suffixes), grouped by module name (`character:`)
146
+ - `locales/common.yml`: language-independent character name components (`character:`) and location proper names (`location:`)
86
147
  - `locales/en/<module>.yml`: English entries for a module
87
148
  - `locales/pl/<module>.yml`: Polish entries for a module
88
149
 
150
+ Location locale files contain templates with a single `%{name}` placeholder, including
151
+ neutral landmark types and dark fantasy prefixes and suffixes.
152
+
89
153
  ```sh
90
154
  bundle install
91
155
  bundle exec rspec
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FantasyFaker
4
+ module Location
5
+ extend BaseModule
6
+ extend self
7
+
8
+ CATEGORIES = %i[
9
+ city sewer meadow forest swamp waters desert cave mine mountain volcanic_field
10
+ ruins stronghold graveyard abandoned_monastery labyrinth_or_arena
11
+ ].freeze
12
+
13
+ CATEGORIES.each do |category|
14
+ define_method(category) { fetch_data(category).rand % { name: fetch_data(:proper_names).rand } }
15
+ end
16
+
17
+ def unique
18
+ @unique_generator ||= begin
19
+ proper_name = /\b#{Regexp.union(fetch_data(:proper_names))}\b/
20
+ UniqueGenerator.new(self) { |name| name[proper_name] }
21
+ end
22
+ end
23
+
24
+ def name
25
+ public_send(CATEGORIES.sample)
26
+ end
27
+ end
28
+ end
@@ -6,8 +6,9 @@ module FantasyFaker
6
6
  class UniqueGenerator
7
7
  class RetryLimitExceeded < RuntimeError; end
8
8
 
9
- def initialize(generator)
9
+ def initialize(generator, &key)
10
10
  @generator = generator
11
+ @key = key
11
12
  @previous_results = Hash.new { |results, method| results[method] = Set.new }
12
13
  end
13
14
 
@@ -20,9 +21,12 @@ module FantasyFaker
20
21
  def method_missing(method, ...)
21
22
  return super unless @generator.respond_to?(method)
22
23
 
24
+ # Custom keys identify values across methods, not within one method.
25
+ previous_results = @previous_results[@key ? nil : method]
23
26
  10_000.times do
24
27
  result = @generator.public_send(method, ...)
25
- return result if @previous_results[method].add?(result)
28
+ key = @key ? @key.call(result) : result
29
+ return result if previous_results.add?(key)
26
30
  end
27
31
 
28
32
  raise RetryLimitExceeded, "Unable to generate a unique #{method} after 10,000 attempts"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FantasyFaker
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/fantasy_faker.rb CHANGED
@@ -5,6 +5,7 @@ require_relative 'fantasy_faker/utils/array_utils'
5
5
  require_relative 'fantasy_faker/unique_generator'
6
6
  require_relative 'fantasy_faker/utils/base_module'
7
7
  require_relative 'fantasy_faker/character'
8
+ require_relative 'fantasy_faker/location'
8
9
 
9
10
  module FantasyFaker
10
11
  DEFAULT_LOCALE = :en