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