unique_names_generator 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c3735cb47c574108e11dde60274f4d2013c0b281fd2bdf08cecc595e9acd2ac
4
- data.tar.gz: 9ccbf1f0f972547de8baabe8675b1a1540ace3a4a24caf3dd88728d86650ba52
3
+ metadata.gz: f9773f651a33cab35886353896b6138a9e1df7d1bbecf1c0573be4da2567eda2
4
+ data.tar.gz: 3dac60147e276911a7c17c505afe95e305800e6aeb897797d925a1844fe2d57d
5
5
  SHA512:
6
- metadata.gz: c049f7832bc38164a17215c3ddaf830b534ec642b25494045f89c39ccb08d7c639a39af7fd061e988173bc7c5190eb8a634f2ebaed562b286d80411cbe77cdb9
7
- data.tar.gz: f9a0be92fb3dbbe8a48bc588b202217d97edcd299f21699a26d7712d9b5129cb8dd0a535ffb7c4f0976bc0377f983f4e047fb9a597800131157262efc623de92
6
+ metadata.gz: 61b362f06916f9f08ab89e91421a4ee0c482433a4d6c9843645d6b02feab966d6197383993425fbf8b1740d211ea53ef149e9d632df0669172755a57be977a32
7
+ data.tar.gz: 0534cb36f75cc5e04fe72c9cdae7e05199880d0e06f1b3e0d7f6f797644f882980356232a79a2c06bb0a54da29ffbdc67f07e22ee6b2e96b9d51548e0aae78e5
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.gem
2
+ .DS_Store
3
+ .yardoc
data/.rubocop.yml CHANGED
@@ -27,5 +27,12 @@ Style/SymbolArray:
27
27
  Exclude:
28
28
  - 'spec/**/*'
29
29
 
30
+ Layout/SpaceInsideBlockBraces:
31
+ Exclude:
32
+ - 'spec/**/*'
33
+
30
34
  Style/NumericPredicate:
31
- Enabled: false
35
+ Enabled: false
36
+
37
+ Metrics/ClassLength:
38
+ Max: 150
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- unique_names_generator (0.1.0)
4
+ unique_names_generator (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -12,7 +12,7 @@ by adding `unique_names_generator` to your list of gemfile dependencies:
12
12
  Add this line to your application's Gemfile:
13
13
 
14
14
  ```
15
- gem 'unique_names_generator', "~> 0.1.0"
15
+ gem 'unique_names_generator', '~> 0.2.0'
16
16
  ```
17
17
 
18
18
  And then execute:
@@ -29,16 +29,19 @@ $ gem install unique_names_generator
29
29
 
30
30
  ## Usage
31
31
 
32
- In a nutshell, you can begin generating randon names with UniqueNamesGenerator by simply specifying an array of one or more dictionaries via `UniqueNamesGenerator.generate`. Available dictionary types are `[:adjectives, :animals, :colors, :languages, :names, :numbers, :star_wars]`.
32
+ In a nutshell, you can begin generating random names with UniqueNamesGenerator by simply creating a Generator instance and specifying an array of one or more dictionaries. Available dictionary types are `[:adjectives, :animals, :colors, :languages, :names, :numbers, :star_wars]`.
33
33
 
34
34
  ```ruby
35
- UniqueNamesGenerator.generate([:adjectives, :animals])
35
+ generator = UniqueNamesGenerator::Generator.new([:adjectives, :animals])
36
+ generator.generate
36
37
  # => Generates ex: "dramatic_limpet"
37
38
 
38
- UniqueNamesGenerator.generate([:adjectives, :colors, :animals])
39
+ generator = UniqueNamesGenerator::Generator.new([:adjectives, :colors, :animals])
40
+ generator.generate
39
41
  # => Generates ex: "tremendous_brown_cat"
40
42
 
41
- UniqueNamesGenerator.generate([:adjectives, :names, :numbers])
43
+ generator = UniqueNamesGenerator::Generator.new([:adjectives, :names, :numbers])
44
+ generator.generate
42
45
  # => Generates ex: "doubtful_wanda_979"
43
46
  ```
44
47
 
@@ -46,7 +49,9 @@ To use custom dictionaries, simply include your array of strings as part of the
46
49
 
47
50
  ```ruby
48
51
  drinks = ['Sprite', 'Coca-Cola', 'Juice', 'Tea']
49
- UniqueNamesGenerator.generate([:colors, drinks])
52
+
53
+ generator = UniqueNamesGenerator::Generator.new([:colors, drinks])
54
+ generator.generate
50
55
  # => Generates ex: "cyan_sprite"
51
56
  ```
52
57
 
@@ -55,17 +60,20 @@ UniqueNamesGenerator.generate([:colors, drinks])
55
60
  UniqueNamesGenerator can be used with either the default provided config (`separator: '_', style: :lowercase, creativity: 0`) or by specifying any of your own configuration options for seeding, seperator, style and creativity.
56
61
 
57
62
  #### More details on possible options
58
-
59
- - **Separator options**: Any ASCII character string such as underscore, dash or blank space. `nil` for no space.
63
+ - **Dictionaries**: [Array<Symbol, Array<String>>] List of dictionaries to use for name generation. Can be symbols referring to built-in dictionaries or custom arrays of strings.
64
+ - **Separator**: [String] Character(s) used to join words in the generated name. Default: '_'. `nil` can be used for no space.
60
65
  - ex: '_', '-', ' ' or `nil` for no space.
61
- - **Style options**: Atom, one of `:lowercase`, `:uppercase`, `:capital`.
62
- - **Creativity options**: An integer or float between 1 and 10.
66
+ - **Style**: [Symbol] Capitalization style for generated names.
67
+ - Options: `:lowercase`, `:uppercase`, `:capital`. Default: `:lowercase`
68
+ - **Creativity**: [Integer] Level of creativity in name generation, affecting word selection. Must be between 0 and 10. A Float value can also be used. Default: 0
63
69
 
64
70
  ```ruby
65
- UniqueNamesGenerator.generate([:colors, :animals], style: :capital, separator: ' ')
71
+ generator = UniqueNamesGenerator::Generator.new([:colors, :animals], style: :capital, separator: ' ')
72
+ generator.generate
66
73
  # => Generates ex: "Lavender Marlin"
67
74
 
68
- UniqueNamesGenerator.generate([:colors, :adjectives, :animals], creativity: 8, style: :capital, separator: ' ')
75
+ generator = UniqueNamesGenerator::Generator.new([:colors, :adjectives, :animals], creativity: 8, style: :capital, separator: ' ')
76
+ generator.generate
69
77
  # => Generates ex: "Yellow Local Hippopotamus"
70
78
  ```
71
79
 
@@ -73,20 +81,22 @@ UniqueNamesGenerator.generate([:colors, :adjectives, :animals], creativity: 8, s
73
81
  Using the creativity option changes how `UniqueNamesGenerator` selects terms from the dictionaries in use, essentially acting as a multiplier. For dictionaries with a similar term length, while using a seed, the selection may at times appear to be alphabetical or closely related (ex: "Amber Anakin Skywalker"). Utilizing the `creative` option with a value between 1 and 10 will use a sequential multiplier for subsequent dictionaries providing a seemingly more "random" or "creative" result whilst still allowing for seeded generation.
74
82
 
75
83
  ```ruby
76
- UniqueNamesGenerator.generate([:colors, :adjectives, :animals], creativity: 8, seed: 'f6da7a28-5ae6-4d6b-b3b8-a197b99ed4eb')
84
+ generator = UniqueNamesGenerator::Generator.new([:colors, :adjectives, :animals], creativity: 8)
85
+ generator.generate(seed: 'f6da7a28-5ae6-4d6b-b3b8-a197b99ed4eb')
77
86
 
78
87
  # => Seed "f6da7a28-5ae6-4d6b-b3b8-a197b99ed4eb" with creativity of 8 always generates: "plum_flying_cobra"
79
88
  ```
80
89
 
81
90
  ### Seeded Generation
82
91
 
83
- A seed can be used to deterministically generate a name. As long as the provided seed and creativity values are the same between runs, then the generated name will also always be the same. Simply provide a string or integer as the value of the seed key, ie; `seed: 'hello'`.
92
+ A seed can be used to deterministically generate a name. As long as the provided seed and creativity values are the same between runs, then the generated name will also always be the same. Simply provide a string or integer as an argument to the generate method, ie; `seed: 'hello'`.
84
93
 
85
- _(**Usecase example:** generate a username for an authenticated user based on UUID. Ex: `13a5d03e-61d0-4b5b-ae3b-57953c268c5f` will always generate the name "beige_boba_fett_145" when used together with the colors/star_wars/numbers dictionaries)._
94
+ _(**Usecase example:** generate a username for an authenticated user based on UUID. Ex: `13a5d03e-61d0-4b5b-ae3b-57953c268c5f` will always generate the name "coral_greedo_320" when used together with the colors/star_wars/numbers dictionaries)._
86
95
 
87
96
  ```ruby
88
- UniqueNamesGenerator.generate([:colors, :star_wars, :numbers], seed: '13a5d03e-61d0-4b5b-ae3b-57953c268c5f')
89
- # => Seed "13a5d03e-61d0-4b5b-ae3b-57953c268c5f" always generates: "beige_boba_fett_145"
97
+ generator = UniqueNamesGenerator::Generator.new([:colors, :star_wars, :numbers])
98
+ generator.generate(seed: '13a5d03e-61d0-4b5b-ae3b-57953c268c5f')
99
+ # => Seed "13a5d03e-61d0-4b5b-ae3b-57953c268c5f" always generates: "coral_greedo_320"
90
100
  ```
91
101
 
92
102
  ## License
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UniqueNamesGenerator
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # An implementation of a unique_names_generator in Ruby
4
- # with support for PRNG/seeds
4
+ # with support for PRNG/deterministic seeds
5
5
 
6
6
  require_relative './unique_names_generator/seed'
7
7
 
@@ -15,178 +15,170 @@ require_relative './unique_names_generator/dictionaries/star_wars'
15
15
 
16
16
  # UniqueNamesGenerator implementation
17
17
  module UniqueNamesGenerator
18
- module_function
19
-
20
- def generate(dictionaries, separator: '_', style: :lowercase, seed: nil, creativity: 0)
21
- @separator = separator
22
- @style = style
23
- @seed = seed
24
- @creativity = creativity
18
+ # UniqueNamesGenerator::Generator
19
+ #
20
+ # This class generates unique names based on specified dictionaries and configuration options.
21
+ # It allows for customizable name generation with various styles, separators, and creativity levels.
22
+ class Generator
23
+ def initialize(dictionaries, separator: '_', style: :lowercase, creativity: 0)
24
+ @dictionaries = dictionaries
25
+ @separator = separator
26
+ @style = style
27
+ @creativity = creativity
28
+
29
+ # Will raise error if any specified dictionary is invalid
30
+ dictionaries.map { |dictionary| word_list(dictionary) }
31
+ raise ArgumentError, 'Outside creativity range. Must be between 0 and 10.' if outside_creativity_bounds?
32
+ end
25
33
 
26
- if creativity.negative? || creativity > 10
27
- raise ArgumentError, 'Outside creativity range. Must be between 0 and 10.'
34
+ def generate(seed: nil)
35
+ @seed = seed
36
+ generate_name(@dictionaries)
28
37
  end
29
38
 
30
- generate_name(dictionaries)
31
- end
39
+ private
32
40
 
33
- def match_word_list(dictionary)
34
- module_name = camelize_dictionary(dictionary)
35
- begin
36
- dictionary = Dictionaries.const_get(module_name)
37
- dictionary.list_all
38
- rescue NameError
39
- raise_invalid_dictionary(dictionary)
41
+ def outside_creativity_bounds?
42
+ @creativity.negative? || @creativity > 10
40
43
  end
41
- end
42
44
 
43
- def word_list(dictionary)
44
- case dictionary
45
- when Array
46
- dictionary if dictionary.all? { |item| item.is_a?(String) }
47
- when Symbol
48
- match_word_list(dictionary)
49
- else
50
- raise ArgumentError, 'Dictionary contains invalid dictionary type'
45
+ def match_word_list(dictionary)
46
+ module_name = camelize_dictionary(dictionary)
47
+ begin
48
+ dictionary = Dictionaries.const_get(module_name)
49
+ dictionary.list_all
50
+ rescue NameError
51
+ raise_invalid_dictionary(dictionary)
52
+ end
51
53
  end
52
- end
53
54
 
54
- def random_seeded_float
55
- seed_value = Seed.generate_seed(@seed)
55
+ def word_list(dictionary)
56
+ case dictionary
57
+ when Array
58
+ dictionary if dictionary.all? { |item| item.is_a?(String) }
59
+ when Symbol
60
+ match_word_list(dictionary)
61
+ else
62
+ raise ArgumentError, 'Dictionary contains invalid dictionary type'
63
+ end
64
+ end
56
65
 
57
- prng = @seed.nil? ? Random.new : Random.new(seed_value)
58
- prng.rand
59
- end
66
+ def random_seeded_float
67
+ seed_value = Seed.generate_seed(@seed)
60
68
 
61
- def map_dictionaries(dictionaries)
62
- dictionaries.map { |dictionary| word_list(dictionary) }
63
- end
69
+ prng = @seed.nil? ? Random.new : Random.new(seed_value)
70
+ prng.rand
71
+ end
64
72
 
65
- def split_with_separator(word)
66
- if @separator.nil?
67
- word.split(/(?=[A-Z])/)
68
- else
69
- word.split(@separator)
73
+ def map_dictionaries(dictionaries)
74
+ dictionaries.map { |dictionary| word_list(dictionary) }
70
75
  end
71
- end
72
76
 
73
- def format_parts(parts)
74
- parts.map do |part|
75
- if part.match?(/[^a-zA-Z]/) && @style == :capital
76
- # Preserve original capitalization for parts with non-letter characters
77
- part
77
+ def split_with_separator(word)
78
+ if @separator.nil?
79
+ word.split(/(?=[A-Z])/)
78
80
  else
79
- format_word(part, @style)
81
+ word.split(@separator)
80
82
  end
81
- end.join(@separator)
82
- end
83
+ end
83
84
 
84
- def format_multi_word(word, original_word)
85
- if original_word.include?(' ') || original_word.include?('-')
86
- parts = split_with_separator(word)
87
- format_parts(parts)
88
- else
89
- format_word(word, @style)
85
+ def format_parts(parts)
86
+ parts.map do |part|
87
+ if part.match?(/[^a-zA-Z]/) && @style == :capital
88
+ # Preserve original capitalization for parts with non-letter characters
89
+ part
90
+ else
91
+ format_word(part, @style)
92
+ end
93
+ end.join(@separator)
90
94
  end
91
- end
92
95
 
93
- def generate_name(dictionaries)
94
- if @creativity.nil? || @creativity.zero?
95
- generate_name_original(dictionaries)
96
- else
97
- generate_name_creatively(dictionaries)
96
+ def format_multi_word(word, original_word)
97
+ if original_word.include?(' ') || original_word.include?('-')
98
+ parts = split_with_separator(word)
99
+ format_parts(parts)
100
+ else
101
+ format_word(word, @style)
102
+ end
98
103
  end
99
- end
100
104
 
101
- def generate_name_original(dictionaries)
102
- map_dictionaries(dictionaries).reduce(nil) do |acc, x|
103
- rnd = (random_seeded_float * x.length).floor
104
- original_word = x[rnd]
105
+ def generate_name(dictionaries)
106
+ if @creativity.nil? || @creativity.zero?
107
+ generate_name_original(dictionaries)
108
+ else
109
+ generate_name_creatively(dictionaries)
110
+ end
111
+ end
105
112
 
106
- output_word(acc, original_word)
113
+ def generate_name_original(dictionaries)
114
+ map_dictionaries(dictionaries).reduce(nil) do |acc, x|
115
+ rnd = (random_seeded_float * x.length).floor
116
+ original_word = x[rnd]
117
+
118
+ output_word(acc, original_word)
119
+ end
107
120
  end
108
- end
109
121
 
110
- def generate_name_creatively(dictionaries)
111
- word_lists = map_dictionaries(dictionaries)
122
+ def generate_name_creatively(dictionaries)
123
+ word_lists = map_dictionaries(dictionaries)
112
124
 
113
- word_lists.each_with_index.reduce(nil) do |acc, (word_list, index)|
114
- creativity = calculate_creativity(index)
115
- rnd = (random_seeded_float * word_list.length * creativity).floor
116
- original_word = word_list[rnd % word_list.length] # Ensure we don't go out of bounds
125
+ word_lists.each_with_index.reduce(nil) do |acc, (word_list, index)|
126
+ creativity = calculate_creativity(index)
127
+ rnd = (random_seeded_float * word_list.length * creativity).floor
128
+ original_word = word_list[rnd % word_list.length] # Ensure we don't go out of bounds
117
129
 
118
- output_word(acc, original_word)
130
+ output_word(acc, original_word)
131
+ end
119
132
  end
120
- end
121
133
 
122
- def output_word(acc, original_word)
123
- word = format_with_separator(original_word)
124
- word = format_multi_word(word, original_word)
134
+ def output_word(acc, original_word)
135
+ word = format_with_separator(original_word)
136
+ word = format_multi_word(word, original_word)
125
137
 
126
- if acc
127
- "#{acc}#{@separator}#{word}"
128
- else
129
- word
138
+ if acc
139
+ "#{acc}#{@separator}#{word}"
140
+ else
141
+ word
142
+ end
130
143
  end
131
- end
132
144
 
133
- def calculate_creativity(index)
134
- if index.zero?
135
- @creativity # Base creativity for the first dictionary
136
- else
137
- @creativity * (2 + index * 0.5) # Increase creativity for subsequent dictionaries
145
+ def calculate_creativity(index)
146
+ if index.zero?
147
+ @creativity # Base creativity for the first dictionary
148
+ else
149
+ @creativity * (2 + index * 0.5) # Increase creativity for subsequent dictionaries
150
+ end
138
151
  end
139
- end
140
152
 
141
- def camelize_dictionary(dictionary)
142
- dictionary.to_s.split('_').map(&:capitalize).join
143
- end
153
+ def camelize_dictionary(dictionary)
154
+ dictionary.to_s.split('_').map(&:capitalize).join
155
+ end
144
156
 
145
- def raise_invalid_dictionary(dictionary)
146
- raise ArgumentError, "Invalid dictionary: #{dictionary}"
147
- end
157
+ def raise_invalid_dictionary(dictionary)
158
+ raise ArgumentError, "Invalid dictionary #{dictionary}"
159
+ end
148
160
 
149
- def format_with_separator(word)
150
- if @separator.nil?
151
- # If separator is empty, just remove spaces without changing case
152
- word.gsub(/\s+/, '')
153
- else
154
- # If there's a separator, use it to replace spaces
155
- word.gsub(/\s+/, @separator)
161
+ def format_with_separator(word)
162
+ if @separator.nil?
163
+ # If separator is empty, just remove spaces without changing case
164
+ word.gsub(/\s+/, '')
165
+ else
166
+ # If there's a separator, use it to replace spaces
167
+ word.gsub(/\s+/, @separator)
168
+ end
156
169
  end
157
- end
158
170
 
159
- def format_word(word, style)
160
- case style
161
- when :lowercase
162
- word.downcase
163
- when :uppercase
164
- word.upcase
165
- when :capital
166
- word.capitalize
167
- else
168
- word
171
+ def format_word(word, style)
172
+ case style
173
+ when :lowercase
174
+ word.downcase
175
+ when :uppercase
176
+ word.upcase
177
+ when :capital
178
+ word.capitalize
179
+ else
180
+ word
181
+ end
169
182
  end
170
183
  end
171
-
172
- private_class_method(
173
- *%i[
174
- generate_name
175
- match_word_list
176
- word_list
177
- random_seeded_float
178
- map_dictionaries
179
- camelize_dictionary
180
- raise_invalid_dictionary
181
- format_with_separator
182
- format_multi_word
183
- format_parts
184
- format_word
185
- split_with_separator
186
- generate_name_original
187
- generate_name_creatively
188
- calculate_creativity
189
- output_word
190
- ]
191
- )
192
184
  end
@@ -15,7 +15,8 @@ Gem::Specification.new do |s|
15
15
  s.email = 'jongirard03@gmail.com'
16
16
  s.homepage = 'https://github.com/jongirard/unique_names_generator_ruby'
17
17
  s.metadata = { 'homepage_uri' => 'https://github.com/jongirard/unique_names_generator_ruby',
18
- 'source_code_uri' => 'https://github.com/jongirard/unique_names_generator_ruby' }
18
+ 'source_code_uri' => 'https://github.com/jongirard/unique_names_generator_ruby',
19
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/unique_names_generator/' }
19
20
  s.require_paths = ['lib']
20
21
  s.license = 'MIT'
21
22
  s.files = Dir.chdir(File.expand_path(__dir__)) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unique_names_generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Girard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-05 00:00:00.000000000 Z
11
+ date: 2024-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -34,6 +34,7 @@ extensions: []
34
34
  extra_rdoc_files: []
35
35
  files:
36
36
  - ".github/workflows/ruby.yml"
37
+ - ".gitignore"
37
38
  - ".pryrc"
38
39
  - ".rspec"
39
40
  - ".rubocop.yml"
@@ -59,6 +60,7 @@ licenses:
59
60
  metadata:
60
61
  homepage_uri: https://github.com/jongirard/unique_names_generator_ruby
61
62
  source_code_uri: https://github.com/jongirard/unique_names_generator_ruby
63
+ documentation_uri: https://www.rubydoc.info/gems/unique_names_generator/
62
64
  post_install_message:
63
65
  rdoc_options: []
64
66
  require_paths: