opaque_id 1.1.0 → 1.3.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.
@@ -0,0 +1,567 @@
1
+ ---
2
+ layout: default
3
+ title: Development
4
+ nav_order: 11
5
+ description: "Development setup, guidelines, and contribution information"
6
+ permalink: /development/
7
+ ---
8
+
9
+ # Development
10
+
11
+ This guide covers development setup, guidelines, and contribution information for OpaqueId. Whether you're contributing to the project or developing applications that use OpaqueId, this guide will help you get started.
12
+
13
+ ## Prerequisites
14
+
15
+ Before you begin development, ensure you have the following installed:
16
+
17
+ ### Required Software
18
+
19
+ - **Ruby 3.2+** - OpaqueId requires modern Ruby features
20
+ - **Rails 8.0+** - For testing and development
21
+ - **Git** - For version control
22
+ - **Bundler** - For dependency management
23
+
24
+ ### Development Tools
25
+
26
+ - **Text Editor/IDE** - VS Code, RubyMine, or your preferred editor
27
+ - **Terminal** - For running commands and tests
28
+ - **Database** - SQLite (for testing), PostgreSQL or MySQL (for production)
29
+
30
+ ## Setup
31
+
32
+ ### 1. Clone the Repository
33
+
34
+ ```bash
35
+ git clone https://github.com/nyaggah/opaque_id.git
36
+ cd opaque_id
37
+ ```
38
+
39
+ ### 2. Install Dependencies
40
+
41
+ ```bash
42
+ bundle install
43
+ ```
44
+
45
+ ### 3. Run Tests
46
+
47
+ ```bash
48
+ bundle exec rake test
49
+ ```
50
+
51
+ ### 4. Run Code Quality Checks
52
+
53
+ ```bash
54
+ bundle exec rubocop
55
+ bundle exec bundle audit --update
56
+ ```
57
+
58
+ ## Development Commands
59
+
60
+ ### Testing
61
+
62
+ ```bash
63
+ # Run all tests
64
+ bundle exec rake test
65
+
66
+ # Run specific test files
67
+ bundle exec ruby test/opaque_id_test.rb
68
+ bundle exec ruby test/opaque_id/model_test.rb
69
+ bundle exec ruby test/opaque_id/generators/install_generator_test.rb
70
+
71
+ # Run tests with verbose output
72
+ bundle exec rake test VERBOSE=true
73
+
74
+ # Run tests with coverage
75
+ bundle exec rake test COVERAGE=true
76
+ ```
77
+
78
+ ### Code Quality
79
+
80
+ ```bash
81
+ # Run RuboCop
82
+ bundle exec rubocop
83
+
84
+ # Auto-correct RuboCop offenses
85
+ bundle exec rubocop --autocorrect
86
+
87
+ # Run security audit
88
+ bundle exec bundle audit --update
89
+
90
+ # Check for outdated dependencies
91
+ bundle outdated
92
+ ```
93
+
94
+ ### Console
95
+
96
+ ```bash
97
+ # Start Rails console with OpaqueId loaded
98
+ bundle exec rails console
99
+
100
+ # Test OpaqueId functionality
101
+ OpaqueId.generate
102
+ OpaqueId.generate(size: 10)
103
+ OpaqueId.generate(alphabet: OpaqueId::STANDARD_ALPHABET)
104
+ ```
105
+
106
+ ### Local Installation
107
+
108
+ ```bash
109
+ # Build the gem
110
+ gem build opaque_id.gemspec
111
+
112
+ # Install locally
113
+ gem install opaque_id-*.gem
114
+
115
+ # Or install from local path
116
+ gem install --local opaque_id-*.gem
117
+ ```
118
+
119
+ ## Project Structure
120
+
121
+ ```
122
+ opaque_id/
123
+ ├── lib/
124
+ │ ├── opaque_id.rb # Main module
125
+ │ ├── opaque_id/
126
+ │ │ ├── model.rb # ActiveRecord concern
127
+ │ │ └── version.rb # Version information
128
+ │ └── generators/
129
+ │ └── opaque_id/
130
+ │ ├── install_generator.rb
131
+ │ └── templates/
132
+ │ └── migration.rb.tt
133
+ ├── test/
134
+ │ ├── opaque_id_test.rb # Core module tests
135
+ │ ├── opaque_id/
136
+ │ │ ├── model_test.rb # Model concern tests
137
+ │ │ └── generators/
138
+ │ │ └── install_generator_test.rb
139
+ │ └── test_helper.rb # Test configuration
140
+ ├── docs/ # Documentation site
141
+ ├── tasks/ # Task lists and PRDs
142
+ ├── .github/
143
+ │ └── workflows/ # GitHub Actions
144
+ ├── Gemfile # Development dependencies
145
+ ├── opaque_id.gemspec # Gem specification
146
+ ├── Rakefile # Rake tasks
147
+ └── README.md # Project documentation
148
+ ```
149
+
150
+ ## Testing Strategy
151
+
152
+ ### Test Coverage
153
+
154
+ OpaqueId maintains comprehensive test coverage across all components:
155
+
156
+ - **Core Module Tests** - ID generation, error handling, edge cases
157
+ - **Model Tests** - ActiveRecord integration, configuration, finder methods
158
+ - **Generator Tests** - Rails generator functionality, file generation
159
+ - **Statistical Tests** - Uniformity and randomness verification
160
+ - **Performance Tests** - Benchmarking and optimization validation
161
+
162
+ ### Test Categories
163
+
164
+ #### Unit Tests
165
+
166
+ ```ruby
167
+ # test/opaque_id_test.rb
168
+ class OpaqueIdTest < Minitest::Test
169
+ def test_generate_default_parameters
170
+ id = OpaqueId.generate
171
+ assert_equal 21, id.length
172
+ assert_match(/\A[A-Za-z0-9]+\z/, id)
173
+ end
174
+
175
+ def test_generate_custom_parameters
176
+ id = OpaqueId.generate(size: 10, alphabet: OpaqueId::STANDARD_ALPHABET)
177
+ assert_equal 10, id.length
178
+ assert_match(/\A[A-Za-z0-9_-]+\z/, id)
179
+ end
180
+ end
181
+ ```
182
+
183
+ #### Integration Tests
184
+
185
+ ```ruby
186
+ # test/opaque_id/model_test.rb
187
+ class ModelTest < Minitest::Test
188
+ def test_automatic_id_generation
189
+ user = User.create!(name: "John Doe")
190
+ assert_not_nil user.opaque_id
191
+ assert_equal 21, user.opaque_id.length
192
+ end
193
+
194
+ def test_finder_methods
195
+ user = User.create!(name: "Jane Smith")
196
+ found_user = User.find_by_opaque_id(user.opaque_id)
197
+ assert_equal user, found_user
198
+ end
199
+ end
200
+ ```
201
+
202
+ #### Generator Tests
203
+
204
+ ```ruby
205
+ # test/opaque_id/generators/install_generator_test.rb
206
+ class InstallGeneratorTest < Minitest::Test
207
+ def test_generator_creates_migration
208
+ generator = create_generator('User')
209
+ generator.invoke_all
210
+
211
+ assert File.exist?('db/migrate/*_add_opaque_id_to_users.rb')
212
+ end
213
+
214
+ def test_generator_updates_model
215
+ generator = create_generator('User')
216
+ generator.invoke_all
217
+
218
+ model_content = File.read('app/models/user.rb')
219
+ assert_includes model_content, 'include OpaqueId::Model'
220
+ end
221
+ end
222
+ ```
223
+
224
+ ### Statistical Testing
225
+
226
+ ```ruby
227
+ def test_statistical_uniformity
228
+ # Generate large sample of IDs
229
+ sample_size = 10000
230
+ ids = sample_size.times.map { OpaqueId.generate }
231
+
232
+ # Analyze character distribution
233
+ all_chars = ids.join.chars
234
+ char_counts = all_chars.tally
235
+
236
+ # Verify uniform distribution
237
+ expected_count = all_chars.size / OpaqueId::ALPHANUMERIC_ALPHABET.size
238
+ char_counts.each_value do |count|
239
+ assert_in_delta expected_count, count, expected_count * 0.3
240
+ end
241
+ end
242
+ ```
243
+
244
+ ## Release Process
245
+
246
+ ### Version Management
247
+
248
+ OpaqueId uses semantic versioning (SemVer) with automated release management:
249
+
250
+ - **Major Version** - Breaking changes
251
+ - **Minor Version** - New features, backward compatible
252
+ - **Patch Version** - Bug fixes, backward compatible
253
+
254
+ ### Release Workflow
255
+
256
+ 1. **Development** - Work on feature branches
257
+ 2. **Testing** - Comprehensive test suite
258
+ 3. **Code Review** - Pull request review process
259
+ 4. **Release** - Automated via GitHub Actions
260
+ 5. **Publishing** - Automatic gem publishing to RubyGems.org
261
+
262
+ ### Release Steps
263
+
264
+ ```bash
265
+ # 1. Update version in lib/opaque_id/version.rb
266
+ # 2. Update CHANGELOG.md
267
+ # 3. Create release commit
268
+ git add .
269
+ git commit -m "Release v1.0.0"
270
+
271
+ # 4. Create and push tag
272
+ git tag v1.0.0
273
+ git push origin v1.0.0
274
+
275
+ # 5. GitHub Actions handles the rest:
276
+ # - Builds the gem
277
+ # - Publishes to RubyGems.org
278
+ # - Creates GitHub release
279
+ ```
280
+
281
+ ## Development Guidelines
282
+
283
+ ### Code Style
284
+
285
+ OpaqueId follows Ruby community standards:
286
+
287
+ - **RuboCop** - Automated code style enforcement
288
+ - **Minitest** - Testing framework
289
+ - **Conventional Commits** - Commit message format
290
+ - **Documentation** - Comprehensive inline documentation
291
+
292
+ ### Commit Messages
293
+
294
+ Use conventional commit format:
295
+
296
+ ```
297
+ feat: add support for custom alphabets
298
+ fix: resolve collision handling edge case
299
+ docs: update installation instructions
300
+ test: add statistical uniformity tests
301
+ refactor: optimize fast path algorithm
302
+ ```
303
+
304
+ ### Pull Request Process
305
+
306
+ 1. **Fork** the repository
307
+ 2. **Create** a feature branch
308
+ 3. **Implement** your changes
309
+ 4. **Add** tests for new functionality
310
+ 5. **Update** documentation
311
+ 6. **Run** the test suite
312
+ 7. **Submit** a pull request
313
+
314
+ ### Code Review Checklist
315
+
316
+ - [ ] Tests pass
317
+ - [ ] Code follows style guidelines
318
+ - [ ] Documentation is updated
319
+ - [ ] No security vulnerabilities
320
+ - [ ] Performance impact considered
321
+ - [ ] Backward compatibility maintained
322
+
323
+ ## Contributing
324
+
325
+ ### Issue Reporting
326
+
327
+ OpaqueId follows an "open source, closed contribution" model. We welcome:
328
+
329
+ - **Bug Reports** - Issues with existing functionality
330
+ - **Feature Requests** - New functionality suggestions
331
+ - **Documentation Improvements** - Better documentation
332
+
333
+ ### Issue Guidelines
334
+
335
+ #### Bug Reports
336
+
337
+ When reporting bugs, include:
338
+
339
+ - **Ruby Version** - `ruby --version`
340
+ - **Rails Version** - `rails --version`
341
+ - **OpaqueId Version** - `gem list opaque_id`
342
+ - **Reproduction Steps** - Clear steps to reproduce
343
+ - **Expected Behavior** - What should happen
344
+ - **Actual Behavior** - What actually happens
345
+ - **Error Messages** - Full error messages and stack traces
346
+
347
+ #### Feature Requests
348
+
349
+ When requesting features, include:
350
+
351
+ - **Use Case** - Why is this feature needed?
352
+ - **Proposed Solution** - How should it work?
353
+ - **Alternatives** - Other solutions considered
354
+ - **Additional Context** - Any other relevant information
355
+
356
+ ### Code of Conduct
357
+
358
+ OpaqueId follows the Contributor Covenant Code of Conduct:
359
+
360
+ - **Be Respectful** - Treat everyone with respect
361
+ - **Be Inclusive** - Welcome people of all backgrounds
362
+ - **Be Constructive** - Provide helpful feedback
363
+ - **Be Professional** - Maintain professional communication
364
+
365
+ ### Community Guidelines
366
+
367
+ - **Ask Questions** - Use GitHub Issues for questions
368
+ - **Share Knowledge** - Help others learn
369
+ - **Report Issues** - Help improve the project
370
+ - **Follow Guidelines** - Respect project standards
371
+
372
+ ## Getting Help
373
+
374
+ ### Documentation
375
+
376
+ - **README.md** - Project overview and quick start
377
+ - **Documentation Site** - Comprehensive guides
378
+ - **API Reference** - Complete method documentation
379
+ - **Examples** - Real-world usage examples
380
+
381
+ ### Support Channels
382
+
383
+ - **GitHub Issues** - Bug reports and feature requests
384
+ - **GitHub Discussions** - Questions and community discussion
385
+ - **Documentation** - Comprehensive guides and examples
386
+
387
+ ### Common Issues
388
+
389
+ #### Installation Issues
390
+
391
+ ```bash
392
+ # Ensure Ruby version compatibility
393
+ ruby --version # Should be 3.2+
394
+
395
+ # Clear gem cache
396
+ gem cleanup
397
+
398
+ # Reinstall dependencies
399
+ bundle install --force
400
+ ```
401
+
402
+ #### Test Failures
403
+
404
+ ```bash
405
+ # Run tests with verbose output
406
+ bundle exec rake test VERBOSE=true
407
+
408
+ # Check test database
409
+ bundle exec rake db:test:prepare
410
+
411
+ # Clear test cache
412
+ bundle exec rake test:prepare
413
+ ```
414
+
415
+ #### Generator Issues
416
+
417
+ ```bash
418
+ # Check Rails version
419
+ rails --version # Should be 8.0+
420
+
421
+ # Verify generator is available
422
+ rails generate opaque_id:install --help
423
+
424
+ # Check model file permissions
425
+ ls -la app/models/
426
+ ```
427
+
428
+ ## Development Environment
429
+
430
+ ### Recommended Setup
431
+
432
+ #### VS Code
433
+
434
+ ```json
435
+ // .vscode/settings.json
436
+ {
437
+ "ruby.rubocop.executePath": "bundle exec",
438
+ "ruby.format": "rubocop",
439
+ "ruby.lint": {
440
+ "rubocop": true
441
+ },
442
+ "files.associations": {
443
+ "*.rb": "ruby",
444
+ "*.gemspec": "ruby"
445
+ }
446
+ }
447
+ ```
448
+
449
+ #### RubyMine
450
+
451
+ - Enable RuboCop integration
452
+ - Configure test runner for Minitest
453
+ - Set up code formatting
454
+ - Enable version control integration
455
+
456
+ ### Development Dependencies
457
+
458
+ ```ruby
459
+ # Gemfile
460
+ group :development, :test do
461
+ gem 'rake', '~> 13.3'
462
+ gem 'sqlite3', '>= 2.1'
463
+ gem 'rubocop', '~> 1.81'
464
+ gem 'rails', '>= 8.0'
465
+ gem 'bundle-audit', '~> 0.1'
466
+ end
467
+ ```
468
+
469
+ ### Environment Variables
470
+
471
+ ```bash
472
+ # .env (for development)
473
+ RAILS_ENV=development
474
+ RUBY_VERSION=3.4.5
475
+ BUNDLE_GEMFILE=Gemfile
476
+ ```
477
+
478
+ ## Performance Development
479
+
480
+ ### Benchmarking
481
+
482
+ ```ruby
483
+ # Benchmark ID generation
484
+ require 'benchmark'
485
+
486
+ def benchmark_generation(count = 1000000)
487
+ puts "Generating #{count} opaque IDs..."
488
+
489
+ time = Benchmark.measure do
490
+ count.times { OpaqueId.generate }
491
+ end
492
+
493
+ puts "Time: #{time.real.round(2)} seconds"
494
+ puts "Rate: #{(count / time.real).round(0)} IDs/second"
495
+ end
496
+
497
+ # Run benchmark
498
+ benchmark_generation(1000000)
499
+ ```
500
+
501
+ ### Memory Profiling
502
+
503
+ ```ruby
504
+ # Memory usage analysis
505
+ require 'memory_profiler'
506
+
507
+ def profile_memory(count = 100000)
508
+ report = MemoryProfiler.report do
509
+ count.times { OpaqueId.generate }
510
+ end
511
+
512
+ puts "Total allocated: #{report.total_allocated_memsize / 1024 / 1024}MB"
513
+ puts "Total retained: #{report.total_retained_memsize / 1024 / 1024}MB"
514
+ end
515
+
516
+ # Run memory profile
517
+ profile_memory(100000)
518
+ ```
519
+
520
+ ### Load Testing
521
+
522
+ ```ruby
523
+ # Concurrent generation testing
524
+ require 'concurrent'
525
+
526
+ def load_test(threads = 10, ids_per_thread = 100000)
527
+ puts "Testing #{threads} threads, #{ids_per_thread} IDs each..."
528
+
529
+ start_time = Time.now
530
+
531
+ # Create thread pool
532
+ pool = Concurrent::FixedThreadPool.new(threads)
533
+
534
+ # Submit tasks
535
+ futures = threads.times.map do
536
+ pool.post do
537
+ ids_per_thread.times.map { OpaqueId.generate }
538
+ end
539
+ end
540
+
541
+ # Wait for completion
542
+ results = futures.map(&:value!)
543
+
544
+ end_time = Time.now
545
+ total_ids = threads * ids_per_thread
546
+ duration = end_time - start_time
547
+
548
+ puts "Total IDs: #{total_ids}"
549
+ puts "Duration: #{duration.round(2)} seconds"
550
+ puts "Rate: #{(total_ids / duration).round(0)} IDs/second"
551
+
552
+ pool.shutdown
553
+ pool.wait_for_termination
554
+ end
555
+
556
+ # Run load test
557
+ load_test(10, 100000)
558
+ ```
559
+
560
+ ## Next Steps
561
+
562
+ Now that you understand development:
563
+
564
+ 1. **Explore [API Reference](api-reference.md)** for complete method documentation
565
+ 2. **Check out [Use Cases](use-cases.md)** for development examples
566
+ 3. **Review [Configuration](configuration.md)** for development configuration
567
+ 4. **Read [Security](security.md)** for security considerations