better_model 1.3.0 โ†’ 2.1.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: 93cc27ca4bb13c22c5d3ac1f0aa96010f7377bf687805b5f76bee89d44b83f5f
4
- data.tar.gz: 5234fde47b3b13fc0ccc2da3fc3948f094ccd0f7eaa2cb4d8d219e6cf291a1c3
3
+ metadata.gz: 3237879bac91f8200057cba591a1a2f09ccc761f55fd2ded1f1acb5a156c65f2
4
+ data.tar.gz: 6ab53b6128104cac44fdb5ad8ce80ca662a78072724a29c946c9380ad66701f2
5
5
  SHA512:
6
- metadata.gz: 3f9394cdc2201586b8b1d510d60aa286d29a86ab1a0c313f61401b850545a1924b08b16489b446d786aac38aa919ff7546dd6e3d3d5c9a9ca8a310b74ecbddc0
7
- data.tar.gz: 8f218e1eb37bc94cb8510cda0ae32033458b1befe2ff5012a766b7c9874865b63b90facb72d7ba97deb1b80175fef06dbf27f6e42b2b9d44d3f47e212908cc7e
6
+ metadata.gz: cf5e0a75c42e6f8c81f76756dd4f292779d1df7e258741bc19877665530a50363d7271c31fcace870d4dc61ac75e7dbd6bf01db3c28857fc29da8ab8e87cbed5
7
+ data.tar.gz: 61992d1b052d377e1db14d312ea3eb024998d2f0e36dcb031fd9e900a3bd35b0add348bfbfb6dc687c41b37ce9df85952924cbb5fb7942abd484af107ce87664
data/README.md CHANGED
@@ -55,11 +55,11 @@ class Article < ApplicationRecord
55
55
  # 6. VALIDATABLE - Declarative validation system (opt-in)
56
56
  validatable do
57
57
  # Basic validations
58
- validate :title, :content, presence: true
58
+ check :title, :content, presence: true
59
59
 
60
60
  # Conditional validations
61
61
  validate_if :is_published? do
62
- validate :published_at, presence: true
62
+ check :published_at, presence: true
63
63
  end
64
64
 
65
65
  # Cross-field validations
@@ -82,10 +82,10 @@ class Article < ApplicationRecord
82
82
 
83
83
  # Define transitions with guards and callbacks
84
84
  transition :publish, from: :draft, to: :published do
85
- guard { valid? }
86
- guard if: :is_ready_for_publishing? # Statusable integration
87
- before { set_published_at }
88
- after { notify_subscribers }
85
+ check { valid? }
86
+ check { title.present? && content.present? }
87
+ before_transition { self.published_at = Time.current }
88
+ after_transition { Rails.logger.info "Article #{id} published" }
89
89
  end
90
90
 
91
91
  transition :archive, from: [:draft, :published], to: :archived
@@ -94,6 +94,9 @@ class Article < ApplicationRecord
94
94
  # 8. TRACEABLE - Audit trail with time-travel (opt-in)
95
95
  traceable do
96
96
  track :title, :content, :status, :published_at
97
+ track :password_hash, sensitive: :full # Complete redaction
98
+ track :credit_card, sensitive: :partial # Pattern-based masking
99
+ track :api_token, sensitive: :hash # SHA256 hashing
97
100
  versions_table :article_versions # Optional: custom table
98
101
  end
99
102
 
@@ -222,24 +225,137 @@ class Article < ApplicationRecord
222
225
  end
223
226
  ```
224
227
 
228
+ ## ๐Ÿ› ๏ธ Generators
229
+
230
+ Better Model provides Rails generators to help you quickly set up migrations for features that require database tables or columns.
231
+
232
+ ### Traceable Generator
233
+
234
+ Create migrations for audit trail version tables:
235
+
236
+ ```bash
237
+ # Basic usage - shows setup instructions
238
+ rails g better_model:traceable Article
239
+
240
+ # Create migration for versions table
241
+ rails g better_model:traceable Article --create-table
242
+
243
+ # Custom table name
244
+ rails g better_model:traceable Article --create-table --table-name=audit_log
245
+
246
+ # Run migrations
247
+ rails db:migrate
248
+ ```
249
+
250
+ **Generated migration includes:**
251
+ - Polymorphic association (`item_type`, `item_id`)
252
+ - Event tracking (`created`, `updated`, `destroyed`)
253
+ - Change tracking (`object_changes` as JSON)
254
+ - User attribution (`updated_by_id`)
255
+ - Change reason (`updated_reason`)
256
+ - Optimized indexes
257
+
258
+ ### Archivable Generator
259
+
260
+ Add soft-delete columns to existing models:
261
+
262
+ ```bash
263
+ # Basic usage - shows setup instructions
264
+ rails g better_model:archivable Article
265
+
266
+ # Add archivable columns to articles table
267
+ rails g better_model:archivable Article --create-columns
268
+
269
+ # Run migrations
270
+ rails db:migrate
271
+ ```
272
+
273
+ **Generated migration adds:**
274
+ - `archived_at` (datetime) - when archived
275
+ - `archived_by_id` (integer) - who archived it
276
+ - `archive_reason` (string) - why archived
277
+ - Index on `archived_at`
278
+
279
+ ### Stateable Generator
280
+
281
+ Create state machine with state column and transitions tracking:
282
+
283
+ ```bash
284
+ # Basic usage - shows setup instructions
285
+ rails g better_model:stateable Article
286
+
287
+ # Create both state column and transitions table
288
+ rails g better_model:stateable Article --create-tables
289
+
290
+ # Custom initial state (default: draft)
291
+ rails g better_model:stateable Article --create-tables --initial-state=pending
292
+
293
+ # Custom transitions table name
294
+ rails g better_model:stateable Article --create-tables --table-name=article_state_history
295
+
296
+ # Run migrations
297
+ rails db:migrate
298
+ ```
299
+
300
+ **Generated migrations include:**
301
+ 1. **State column migration:**
302
+ - `state` (string) with default value and index
303
+
304
+ 2. **Transitions table migration:**
305
+ - Polymorphic association (`transitionable_type`, `transitionable_id`)
306
+ - Event name and state tracking
307
+ - Optional metadata (JSON)
308
+ - Optimized indexes
309
+
310
+ ### Generator Options
311
+
312
+ All generators support these common options:
313
+
314
+ - `--pretend` - Dry run, show what would be generated
315
+ - `--skip-model` - Only generate migrations, don't show model setup instructions
316
+ - `--force` - Overwrite existing files
317
+
318
+ **Example workflow:**
319
+
320
+ ```bash
321
+ # 1. Generate migrations (dry-run first to preview)
322
+ rails g better_model:traceable Article --create-table --pretend
323
+ rails g better_model:archivable Article --create-columns --pretend
324
+ rails g better_model:stateable Article --create-tables --pretend
325
+
326
+ # 2. Generate for real
327
+ rails g better_model:traceable Article --create-table
328
+ rails g better_model:archivable Article --create-columns
329
+ rails g better_model:stateable Article --create-tables
330
+
331
+ # 3. Run migrations
332
+ rails db:migrate
333
+
334
+ # 4. Enable in your model (generators show you the code)
335
+ # See model setup instructions after running each generator
336
+ ```
337
+
225
338
  ## ๐Ÿ“‹ Features Overview
226
339
 
227
340
  BetterModel provides ten powerful concerns that work seamlessly together:
228
341
 
229
- ### Core Features
342
+ ### Core Features (Always Available)
230
343
 
231
344
  - **โœจ Statusable** - Declarative status management with lambda-based conditions
232
345
  - **๐Ÿ” Permissible** - State-based permission system
233
- - **๐Ÿ—„๏ธ Archivable** - Soft delete with tracking (by user, reason)
234
- - **โฐ Traceable** - Complete audit trail with time-travel and rollback
235
346
  - **โฌ†๏ธ Sortable** - Type-aware sorting scopes
236
347
  - **๐Ÿ” Predicable** - Advanced filtering with rich predicate system
348
+
349
+ ### Opt-in Features (Require Activation)
350
+
237
351
  - **๐Ÿ”Ž Searchable** - Unified search interface (Predicable + Sortable)
352
+ - **๐Ÿ—„๏ธ Archivable** - Soft delete with tracking (by user, reason)
238
353
  - **โœ… Validatable** - Declarative validation DSL with conditional rules
239
354
  - **๐Ÿ”„ Stateable** - Declarative state machines with guards & callbacks
355
+ - **โฐ Traceable** - Complete audit trail with time-travel and rollback
240
356
  - **๐Ÿท๏ธ Taggable** ๐Ÿ†• - Tag management with normalization, validation, and statistics
241
357
 
242
- [See all features in detail โ†’](#-features)
358
+ [See all features in detail โ†’](#feature-details)
243
359
 
244
360
  ## โš™๏ธ Requirements
245
361
 
@@ -263,9 +379,22 @@ BetterModel works with all databases supported by ActiveRecord:
263
379
  - Array predicates: `overlaps`, `contains`, `contained_by`
264
380
  - JSONB predicates: `has_key`, `has_any_key`, `has_all_keys`, `jsonb_contains`
265
381
 
266
- ## ๐Ÿ“š Features
382
+ ## ๐Ÿ—„๏ธ Database Requirements
383
+
384
+ Some opt-in features require database columns. Use the provided generators to add them:
385
+
386
+ | Feature | Database Requirement | Generator Command |
387
+ |---------|---------------------|-------------------|
388
+ | **Archivable** | `archived_at` column | `rails g better_model:archivable Model` |
389
+ | **Stateable** | `state`, `transitions` columns | `rails g better_model:stateable Model` |
390
+ | **Traceable** | `version_records` table | `rails g better_model:traceable Model` |
391
+ | **Taggable** | `tags` JSONB/text column | `rails g better_model:taggable Model` |
267
392
 
268
- BetterModel provides eight powerful concerns that work together seamlessly:
393
+ **Core features** (Statusable, Permissible, Predicable, Sortable, Searchable, Validatable) require no database changes.
394
+
395
+ ## ๐Ÿ“š Feature Details
396
+
397
+ BetterModel provides ten powerful concerns that work together seamlessly:
269
398
 
270
399
  ### ๐Ÿ“‹ Statusable - Declarative Status Management
271
400
 
@@ -358,10 +487,11 @@ Track all changes to your records with complete audit trail, time-travel capabil
358
487
  **๐ŸŽฏ Key Benefits:**
359
488
  - ๐ŸŽ›๏ธ Opt-in activation: only enabled when explicitly configured
360
489
  - ๐Ÿ“ Automatic change tracking on create, update, and destroy
490
+ - ๐Ÿ” Sensitive data protection: 3-level redaction system (full, partial, hash)
361
491
  - ๐Ÿ‘ค User attribution: track who made each change
362
492
  - ๐Ÿ’ฌ Change reasons: optional context for changes
363
493
  - โฐ Time-travel: reconstruct object state at any point in history
364
- - โ†ฉ๏ธ Rollback support: restore records to previous versions
494
+ - โ†ฉ๏ธ Rollback support: restore records to previous versions (with sensitive field protection)
365
495
  - ๐Ÿ” Rich query API: find changes by user, time, or field transitions
366
496
  - ๐Ÿ“Š Flexible table naming: per-model, shared, or custom tables
367
497
  - ๐Ÿ”— Polymorphic association for efficient storage
@@ -398,9 +528,75 @@ Generate comprehensive predicate scopes for filtering and searching with support
398
528
  - ๐Ÿ“Š Range queries (between) for numerics and dates
399
529
  - ๐Ÿ˜ PostgreSQL array and JSONB support
400
530
  - ๐Ÿ”— Chainable with standard ActiveRecord queries
531
+ - ๐Ÿงฉ Custom complex predicates for business logic
401
532
 
402
533
  **[๐Ÿ“– Full Documentation โ†’](docs/predicable.md)**
403
534
 
535
+ #### ๐Ÿงฉ Complex Predicates
536
+
537
+ For queries that go beyond single-field filtering, you can register **complex predicates** - custom scopes that combine multiple conditions, work with associations, or encapsulate business logic.
538
+
539
+ **Basic Example:**
540
+
541
+ ```ruby
542
+ class Article < ApplicationRecord
543
+ include BetterModel
544
+
545
+ predicates :title, :view_count, :published_at
546
+
547
+ # Define a complex predicate with parameters
548
+ register_complex_predicate :trending do |days = 7, min_views = 100|
549
+ where("published_at >= ? AND view_count >= ?", days.days.ago, min_views)
550
+ end
551
+
552
+ # Define a complex predicate for association queries
553
+ register_complex_predicate :popular_author do |min_articles = 10|
554
+ joins(:author)
555
+ .group("articles.author_id")
556
+ .having("COUNT(articles.id) >= ?", min_articles)
557
+ end
558
+ end
559
+ ```
560
+
561
+ **Usage:**
562
+
563
+ ```ruby
564
+ # Use with default parameters
565
+ Article.trending
566
+ # => Articles from last 7 days with 100+ views
567
+
568
+ # Use with custom parameters
569
+ Article.trending(14, 200)
570
+ # => Articles from last 14 days with 200+ views
571
+
572
+ # Chain with standard predicates
573
+ Article.trending(7, 100)
574
+ .title_cont("Ruby")
575
+ .status_eq("published")
576
+ .sort_view_count_desc
577
+
578
+ # Association-based queries
579
+ Article.popular_author(5)
580
+ .published_at_within(30.days)
581
+ ```
582
+
583
+ **When to Use Complex Predicates:**
584
+
585
+ | Standard Predicates โœ… | Complex Predicates ๐Ÿงฉ |
586
+ |------------------------|------------------------|
587
+ | Single field filtering | Multi-field conditions |
588
+ | `title_eq("Ruby")` | `trending(days, views)` |
589
+ | `view_count_gt(100)` | Association queries |
590
+ | `published_at_within(7.days)` | Business logic encapsulation |
591
+ | Simple comparisons | Custom SQL expressions |
592
+
593
+ **Check if Defined:**
594
+
595
+ ```ruby
596
+ Article.complex_predicate?(:trending) # => true
597
+ Article.complex_predicates_registry # => { trending: #<Proc> }
598
+ ```
599
+
404
600
  ---
405
601
 
406
602
  ### ๐Ÿ”Ž Searchable - Unified Search Interface
@@ -415,9 +611,54 @@ Orchestrate Predicable and Sortable into a powerful, secure search interface wit
415
611
  - โš™๏ธ Default ordering configuration
416
612
  - ๐Ÿ’ช Strong parameters integration
417
613
  - โœ… Type-safe validation of all parameters
614
+ - ๐Ÿš€ Eager loading support with `includes:`, `preload:`, `eager_load:`
418
615
 
419
616
  **[๐Ÿ“– Full Documentation โ†’](docs/searchable.md)**
420
617
 
618
+ #### ๐Ÿ”— Eager Loading Associations
619
+
620
+ Optimize N+1 queries with built-in eager loading support:
621
+
622
+ ```ruby
623
+ # Single association (always use array syntax)
624
+ Article.search(
625
+ { status_eq: "published" },
626
+ includes: [:author]
627
+ )
628
+
629
+ # Multiple associations
630
+ Article.search(
631
+ { status_eq: "published" },
632
+ includes: [:author, :comments],
633
+ preload: [:tags]
634
+ )
635
+
636
+ # Nested associations
637
+ Article.search(
638
+ { status_eq: "published" },
639
+ includes: [{ author: :profile }]
640
+ )
641
+
642
+ # Complex mix of associations
643
+ Article.search(
644
+ { status_eq: "published" },
645
+ includes: [:tags, { author: :profile }, { comments: :user }]
646
+ )
647
+
648
+ # Combined with pagination and ordering
649
+ Article.search(
650
+ { status_eq: "published" },
651
+ pagination: { page: 1, per_page: 25 },
652
+ orders: [:sort_view_count_desc],
653
+ includes: [:author, :comments]
654
+ )
655
+ ```
656
+
657
+ **Strategies:**
658
+ - `includes:` - Smart loading (LEFT OUTER JOIN or separate queries)
659
+ - `preload:` - Separate queries (avoids JOIN ambiguity)
660
+ - `eager_load:` - Force LEFT OUTER JOIN (use with caution with default_order)
661
+
421
662
  ---
422
663
 
423
664
  ### ๐Ÿท๏ธ Taggable - Tag Management with Statistics
@@ -438,147 +679,6 @@ Manage tags with automatic normalization, validation, and comprehensive statisti
438
679
 
439
680
  ---
440
681
 
441
- ### ๐Ÿ“œ Traceable - Audit Trail & Change Tracking
442
-
443
- Track all changes to your records with comprehensive audit trail functionality, time-travel queries, and rollback capabilities.
444
-
445
- **๐ŸŽฏ Key Benefits:**
446
- - ๐ŸŽ›๏ธ Opt-in activation: only enabled when explicitly configured
447
- - ๐Ÿค– Automatic change tracking on create/update/destroy
448
- - โฐ Time-travel: reconstruct record state at any point in time
449
- - โ†ฉ๏ธ Rollback: restore to previous versions
450
- - ๐Ÿ“ Audit trail with who/why tracking
451
- - ๐Ÿ” Query changes by user, date range, or field transitions
452
- - ๐Ÿ—‚๏ธ Flexible table naming: per-model tables (default), shared table, or custom names
453
-
454
- **[๐Ÿ“– Full Documentation โ†’](docs/traceable.md)**
455
-
456
- #### ๐Ÿš€ Quick Setup
457
-
458
- **1๏ธโƒฃ Step 1: Create the versions table**
459
-
460
- By default, each model gets its own versions table (`{model}_versions`):
461
-
462
- ```bash
463
- # Creates migration for article_versions table
464
- rails g better_model:traceable Article --create-table
465
- rails db:migrate
466
- ```
467
-
468
- Or use a custom table name:
469
-
470
- ```bash
471
- # Creates migration for custom table name
472
- rails g better_model:traceable Article --create-table --table-name=audit_log
473
- rails db:migrate
474
- ```
475
-
476
- **2๏ธโƒฃ Step 2: Enable in your model**
477
-
478
- ```ruby
479
- class Article < ApplicationRecord
480
- include BetterModel
481
-
482
- # Activate traceable (opt-in)
483
- traceable do
484
- track :status, :title, :published_at # Fields to track
485
- # versions_table 'audit_log' # Optional: custom table (default: article_versions)
486
- end
487
- end
488
- ```
489
-
490
- **๐Ÿ’ก Usage:**
491
-
492
- ```ruby
493
- # ๐Ÿค– Automatic tracking on changes
494
- article.update!(status: "published", updated_by_id: user.id, updated_reason: "Approved")
495
-
496
- # ๐Ÿ” Query version history
497
- article.versions # All versions (ordered desc)
498
- article.changes_for(:status) # Changes for specific field
499
- article.audit_trail # Full formatted history
500
-
501
- # โฐ Time-travel: reconstruct state at specific time
502
- past_article = article.as_of(3.days.ago)
503
- past_article.status # => "draft" (what it was 3 days ago)
504
-
505
- # โ†ฉ๏ธ Rollback to previous version
506
- version = article.versions.where(event: "updated").first
507
- article.rollback_to(version, updated_by_id: user.id, updated_reason: "Mistake")
508
-
509
- # ๐Ÿ“Š Class-level queries
510
- Article.changed_by(user.id) # Records changed by user
511
- Article.changed_between(1.week.ago, Time.current) # Changes in period
512
- Article.status_changed_from("draft").to("published") # Specific transitions (PostgreSQL)
513
-
514
- # ๐Ÿ“ฆ Integration with as_json
515
- article.as_json(include_audit_trail: true) # Include full history in JSON
516
- ```
517
-
518
- **๐Ÿ’พ Database Schema:**
519
-
520
- By default, each model gets its own versions table (e.g., `article_versions` for Article model).
521
- You can also use a shared table across multiple models or a custom table name.
522
-
523
- | Column | Type | Description |
524
- |--------|------|-------------|
525
- | `item_type` | string | Polymorphic model name |
526
- | `item_id` | integer | Polymorphic record ID |
527
- | `event` | string | Event type: created/updated/destroyed |
528
- | `object_changes` | json | Before/after values for tracked fields |
529
- | `updated_by_id` | integer | Optional: user who made the change |
530
- | `updated_reason` | string | Optional: reason for the change |
531
- | `created_at` | datetime | When the change occurred |
532
-
533
- **๐Ÿ—‚๏ธ Table Naming Options:**
534
-
535
- ```ruby
536
- # 1๏ธโƒฃ Option 1: Per-model table (default)
537
- class Article < ApplicationRecord
538
- traceable do
539
- track :status
540
- # Uses article_versions table automatically
541
- end
542
- end
543
-
544
- # 2๏ธโƒฃ Option 2: Custom table name
545
- class Article < ApplicationRecord
546
- traceable do
547
- track :status
548
- versions_table 'audit_log' # Uses audit_log table
549
- end
550
- end
551
-
552
- # 3๏ธโƒฃ Option 3: Shared table across models
553
- class Article < ApplicationRecord
554
- traceable do
555
- track :status
556
- versions_table 'versions' # Shared table
557
- end
558
- end
559
-
560
- class User < ApplicationRecord
561
- traceable do
562
- track :email
563
- versions_table 'versions' # Same shared table
564
- end
565
- end
566
- ```
567
-
568
- **๐Ÿ“ Optional Tracking:**
569
-
570
- To track who made changes and why, simply set attributes before saving:
571
-
572
- ```ruby
573
- article.updated_by_id = current_user.id
574
- article.updated_reason = "Fixed typo"
575
- article.update!(title: "Corrected Title")
576
-
577
- # The version will automatically include updated_by_id and updated_reason
578
- ```
579
-
580
- ---
581
-
582
682
  ## ๐Ÿ“Œ Changelog
583
683
 
584
684
  See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
@@ -604,22 +704,15 @@ Detailed documentation for each BetterModel concern:
604
704
  - [**Searchable**](docs/searchable.md) - Unified search interface
605
705
  - [**Validatable**](docs/validatable.md) - Declarative validation system
606
706
  - [**Stateable**](docs/stateable.md) ๐Ÿ†• - State machine with transitions
607
-
608
- ### ๐ŸŽ“ Advanced Guides
609
-
610
- Learn how to master BetterModel in production:
611
-
612
- - [**Integration Guide**](docs/integration_guide.md) ๐Ÿ†• - Combining multiple concerns effectively
613
- - [**Performance Guide**](docs/performance_guide.md) ๐Ÿ†• - Optimization strategies and indexing
614
- - [**Migration Guide**](docs/migration_guide.md) ๐Ÿ†• - Adding BetterModel to existing apps
707
+ - [**Taggable**](docs/taggable.md) ๐Ÿ†• - Flexible tag management with normalization
615
708
 
616
709
  ### ๐Ÿ’ก Quick Links
617
710
 
618
- - [Installation](#-installation)
619
- - [Quick Start](#-quick-start)
620
- - [Features Overview](#-features-overview)
621
- - [Requirements](#%EF%B8%8F-requirements)
622
- - [Contributing](#-contributing)
711
+ - [Installation](#installation)
712
+ - [Quick Start](#quick-start)
713
+ - [Features Overview](#features-overview)
714
+ - [Requirements](#requirements)
715
+ - [Contributing](#contributing)
623
716
 
624
717
  ## ๐Ÿค Contributing
625
718
 
@@ -648,6 +741,35 @@ We welcome contributions! Here's how you can help:
648
741
 
649
742
  ### ๐Ÿ”ง Development Setup
650
743
 
744
+ #### ๐Ÿณ Using Docker (Recommended)
745
+
746
+ The easiest way to get started is with Docker, which provides a consistent development environment:
747
+
748
+ ```bash
749
+ # Clone your fork
750
+ git clone https://github.com/YOUR_USERNAME/better_model.git
751
+ cd better_model
752
+
753
+ # One-time setup: build image and install dependencies
754
+ bin/docker-setup
755
+
756
+ # Run tests
757
+ bin/docker-test
758
+
759
+ # Run RuboCop
760
+ bin/docker-rubocop
761
+
762
+ # Open interactive shell for debugging
763
+ docker compose run --rm app sh
764
+
765
+ # Run any command in the container
766
+ docker compose run --rm app bundle exec [command]
767
+ ```
768
+
769
+ #### ๐Ÿ’ป Local Setup (Without Docker)
770
+
771
+ If you prefer to use your local Ruby installation:
772
+
651
773
  ```bash
652
774
  # Clone your fork
653
775
  git clone https://github.com/YOUR_USERNAME/better_model.git
@@ -666,6 +788,11 @@ bundle exec rake test # Coverage report in coverage/index.html
666
788
  bundle exec rubocop
667
789
  ```
668
790
 
791
+ **Requirements:**
792
+ - Ruby 3.0+ (Ruby 3.3 recommended)
793
+ - Rails 8.1+
794
+ - SQLite3
795
+
669
796
  ### ๐Ÿ“Š Test Coverage Notes
670
797
 
671
798
  The test suite runs on **SQLite** for performance and portability. Current coverage: **92.57%** (1507 / 1628 lines).
@@ -698,3 +825,13 @@ All code has inline comments marking database-specific sections for maintainabil
698
825
  ## ๐Ÿ“ License
699
826
 
700
827
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
828
+
829
+ ---
830
+
831
+ <div align="center">
832
+
833
+ **Made with โค๏ธ by [Alessio Bussolari](https://github.com/alessiobussolari)**
834
+
835
+ [Report Bug](https://github.com/alessiobussolari/better_model/issues) ยท [Request Feature](https://github.com/alessiobussolari/better_model/issues) ยท [Documentation](https://github.com/alessiobussolari/better_model)
836
+
837
+ </div>
@@ -104,8 +104,8 @@ module BetterModel
104
104
  sort :archived_at unless sortable_field?(:archived_at)
105
105
 
106
106
  # Definisci gli scope alias (approccio ibrido)
107
- scope :archived, -> { archived_at_present }
108
- scope :not_archived, -> { archived_at_null }
107
+ scope :archived, -> { archived_at_present(true) }
108
+ scope :not_archived, -> { archived_at_null(true) }
109
109
 
110
110
  # Configura se passato un blocco
111
111
  if block_given?