iml 0.1.5 → 0.2.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 +5 -5
- data/.claude/settings.local.json +7 -0
- data/.github/workflows/ci.yml +30 -0
- data/.github/workflows/publish.yml +32 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +108 -68
- data/PLAN.md +350 -0
- data/README.md +79 -23
- data/Rakefile +9 -8
- data/TODO.md +43 -0
- data/bin/iml +80 -70
- data/gemspec.yml +7 -13
- data/iml.gemspec +22 -31
- data/lib/iml/configuration.rb +49 -0
- data/lib/iml/file_mover.rb +20 -0
- data/lib/iml/formatter.rb +16 -0
- data/lib/iml/media/movie.rb +30 -0
- data/lib/iml/media/tv_series.rb +45 -0
- data/lib/iml/normalizer.rb +79 -0
- data/lib/iml/parser.rb +39 -0
- data/lib/iml/pattern_builder.rb +42 -0
- data/lib/iml/version.rb +1 -1
- data/lib/iml.rb +34 -21
- data/patterns.yml +36 -1
- metadata +34 -117
- data/.rubocop.yml +0 -17
- data/.travis.yml +0 -7
- data/fixtures/vcr_cassettes/IML_Base_imdb.yml +0 -841
- data/fixtures/vcr_cassettes/IML_IMDB_new.yml +0 -59
- data/lib/iml/base.rb +0 -139
- data/lib/iml/hash.rb +0 -14
- data/lib/iml/imdb.rb +0 -71
- data/lib/iml/movie.rb +0 -24
- data/lib/iml/patterns.rb +0 -64
- data/lib/iml/text.rb +0 -51
- data/lib/iml/tvseries.rb +0 -38
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0df9f622d736c3aa7a80b02aa71d1b038dfb0a3f2f6f050d09a8a012c0e1c6fc
|
|
4
|
+
data.tar.gz: 72ae2f50c874deec6f145861114a14d4d3cff71a80dbbc74a127bd80d841958c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee56baf5a3197379b45cae3065881ef7f2a2517e60434c4cc54a16a55a8e9afd57ef8edf85f94c895e0256ed99ff7190d553a8113bd1acb7757f097b8865cb1e
|
|
7
|
+
data.tar.gz: 89aba00474efb6bda24faf7c9ba76c8b17cd6d691602a1f1712299c6c33c160fdf4578674d433f7daf4b79f93805d936e82b0d7b5a95b083df33fd2564a6df0c
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
ruby-version: ['3.1', '3.2', '3.3']
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Ruby
|
|
21
|
+
uses: ruby/setup-ruby@v1
|
|
22
|
+
with:
|
|
23
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
24
|
+
bundler-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: bundle exec rspec
|
|
28
|
+
|
|
29
|
+
- name: Run linter
|
|
30
|
+
run: bundle exec standardrb
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Publish Gem
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
packages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
publish:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Ruby
|
|
21
|
+
uses: ruby/setup-ruby@v1
|
|
22
|
+
with:
|
|
23
|
+
ruby-version: '3.3'
|
|
24
|
+
bundler-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Publish to RubyGems
|
|
27
|
+
uses: rubygems/release-gem@v1
|
|
28
|
+
|
|
29
|
+
- name: Publish to GitHub Packages
|
|
30
|
+
env:
|
|
31
|
+
GEM_HOST_API_KEY: "Bearer ${{ secrets.GITHUB_TOKEN }}"
|
|
32
|
+
run: gem push --host https://rubygems.pkg.github.com/${{ github.repository_owner }} pkg/*.gem
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,87 +1,127 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
iml (0.
|
|
5
|
-
activesupport (~> 5.2)
|
|
6
|
-
nokogiri (~> 1.8)
|
|
7
|
-
tqdm (~> 0.3)
|
|
4
|
+
iml (0.2.0)
|
|
8
5
|
|
|
9
6
|
GEM
|
|
10
7
|
remote: https://rubygems.org/
|
|
11
8
|
specs:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
nokogiri (1.8.4)
|
|
35
|
-
mini_portile2 (~> 2.3.0)
|
|
36
|
-
pry (0.11.3)
|
|
37
|
-
coderay (~> 1.1.0)
|
|
38
|
-
method_source (~> 0.9.0)
|
|
39
|
-
public_suffix (3.0.2)
|
|
40
|
-
rake (12.3.1)
|
|
41
|
-
rspec (3.7.0)
|
|
42
|
-
rspec-core (~> 3.7.0)
|
|
43
|
-
rspec-expectations (~> 3.7.0)
|
|
44
|
-
rspec-mocks (~> 3.7.0)
|
|
45
|
-
rspec-core (3.7.1)
|
|
46
|
-
rspec-support (~> 3.7.0)
|
|
47
|
-
rspec-expectations (3.7.0)
|
|
9
|
+
ast (2.4.3)
|
|
10
|
+
diff-lcs (1.6.2)
|
|
11
|
+
docile (1.4.1)
|
|
12
|
+
json (2.18.1)
|
|
13
|
+
language_server-protocol (3.17.0.5)
|
|
14
|
+
lint_roller (1.1.0)
|
|
15
|
+
parallel (1.27.0)
|
|
16
|
+
parser (3.3.10.1)
|
|
17
|
+
ast (~> 2.4.1)
|
|
18
|
+
racc
|
|
19
|
+
prism (1.9.0)
|
|
20
|
+
racc (1.8.1)
|
|
21
|
+
rainbow (3.1.1)
|
|
22
|
+
rake (13.3.1)
|
|
23
|
+
regexp_parser (2.11.3)
|
|
24
|
+
rspec (3.13.2)
|
|
25
|
+
rspec-core (~> 3.13.0)
|
|
26
|
+
rspec-expectations (~> 3.13.0)
|
|
27
|
+
rspec-mocks (~> 3.13.0)
|
|
28
|
+
rspec-core (3.13.6)
|
|
29
|
+
rspec-support (~> 3.13.0)
|
|
30
|
+
rspec-expectations (3.13.5)
|
|
48
31
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
49
|
-
rspec-support (~> 3.
|
|
50
|
-
rspec-mocks (3.7
|
|
32
|
+
rspec-support (~> 3.13.0)
|
|
33
|
+
rspec-mocks (3.13.7)
|
|
51
34
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
52
|
-
rspec-support (~> 3.
|
|
53
|
-
rspec-support (3.7
|
|
54
|
-
|
|
55
|
-
|
|
35
|
+
rspec-support (~> 3.13.0)
|
|
36
|
+
rspec-support (3.13.7)
|
|
37
|
+
rubocop (1.82.1)
|
|
38
|
+
json (~> 2.3)
|
|
39
|
+
language_server-protocol (~> 3.17.0.2)
|
|
40
|
+
lint_roller (~> 1.1.0)
|
|
41
|
+
parallel (~> 1.10)
|
|
42
|
+
parser (>= 3.3.0.2)
|
|
43
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
44
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
45
|
+
rubocop-ast (>= 1.48.0, < 2.0)
|
|
46
|
+
ruby-progressbar (~> 1.7)
|
|
47
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
48
|
+
rubocop-ast (1.49.0)
|
|
49
|
+
parser (>= 3.3.7.2)
|
|
50
|
+
prism (~> 1.7)
|
|
51
|
+
rubocop-performance (1.26.1)
|
|
52
|
+
lint_roller (~> 1.1)
|
|
53
|
+
rubocop (>= 1.75.0, < 2.0)
|
|
54
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
55
|
+
ruby-progressbar (1.13.0)
|
|
56
|
+
simplecov (0.22.0)
|
|
56
57
|
docile (~> 1.1)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
simplecov-html (0.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
simplecov-html (~> 0.11)
|
|
59
|
+
simplecov_json_formatter (~> 0.1)
|
|
60
|
+
simplecov-html (0.13.2)
|
|
61
|
+
simplecov_json_formatter (0.1.4)
|
|
62
|
+
standard (1.53.0)
|
|
63
|
+
language_server-protocol (~> 3.17.0.2)
|
|
64
|
+
lint_roller (~> 1.0)
|
|
65
|
+
rubocop (~> 1.82.0)
|
|
66
|
+
standard-custom (~> 1.0.0)
|
|
67
|
+
standard-performance (~> 1.8)
|
|
68
|
+
standard-custom (1.0.2)
|
|
69
|
+
lint_roller (~> 1.0)
|
|
70
|
+
rubocop (~> 1.50)
|
|
71
|
+
standard-performance (1.9.0)
|
|
72
|
+
lint_roller (~> 1.1)
|
|
73
|
+
rubocop-performance (~> 1.26.0)
|
|
74
|
+
unicode-display_width (3.2.0)
|
|
75
|
+
unicode-emoji (~> 4.1)
|
|
76
|
+
unicode-emoji (4.2.0)
|
|
77
|
+
yard (0.9.38)
|
|
70
78
|
|
|
71
79
|
PLATFORMS
|
|
80
|
+
arm64-darwin-25
|
|
72
81
|
ruby
|
|
73
82
|
|
|
74
83
|
DEPENDENCIES
|
|
75
|
-
bundler (
|
|
76
|
-
codeclimate-test-reporter (~> 1.0)
|
|
84
|
+
bundler (>= 2.4)
|
|
77
85
|
iml!
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
vcr (~> 4.0)
|
|
83
|
-
webmock (~> 3.4)
|
|
86
|
+
rake (~> 13.0)
|
|
87
|
+
rspec (~> 3.13)
|
|
88
|
+
simplecov (~> 0.22)
|
|
89
|
+
standard (~> 1.40)
|
|
84
90
|
yard (~> 0.9)
|
|
85
91
|
|
|
92
|
+
CHECKSUMS
|
|
93
|
+
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
|
|
94
|
+
diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
|
|
95
|
+
docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
|
|
96
|
+
iml (0.2.0)
|
|
97
|
+
json (2.18.1) sha256=fe112755501b8d0466b5ada6cf50c8c3f41e897fa128ac5d263ec09eedc9f986
|
|
98
|
+
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
|
|
99
|
+
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
|
|
100
|
+
parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
|
|
101
|
+
parser (3.3.10.1) sha256=06f6a725d2cd91e5e7f2b7c32ba143631e1f7c8ae2fb918fc4cebec187e6a688
|
|
102
|
+
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
|
|
103
|
+
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
|
104
|
+
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
|
|
105
|
+
rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
|
|
106
|
+
regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4
|
|
107
|
+
rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
|
|
108
|
+
rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
|
|
109
|
+
rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
|
|
110
|
+
rspec-mocks (3.13.7) sha256=0979034e64b1d7a838aaaddf12bf065ea4dc40ef3d4c39f01f93ae2c66c62b1c
|
|
111
|
+
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
|
|
112
|
+
rubocop (1.82.1) sha256=09f1a6a654a960eda767aebea33e47603080f8e9c9a3f019bf9b94c9cab5e273
|
|
113
|
+
rubocop-ast (1.49.0) sha256=49c3676d3123a0923d333e20c6c2dbaaae2d2287b475273fddee0c61da9f71fd
|
|
114
|
+
rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834
|
|
115
|
+
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
|
|
116
|
+
simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
|
|
117
|
+
simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
|
|
118
|
+
simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
|
|
119
|
+
standard (1.53.0) sha256=f3c9493385db7079d0abce6f7582f553122156997b81258cd361d3480eeacf9c
|
|
120
|
+
standard-custom (1.0.2) sha256=424adc84179a074f1a2a309bb9cf7cd6bfdb2b6541f20c6bf9436c0ba22a652b
|
|
121
|
+
standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2
|
|
122
|
+
unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
|
|
123
|
+
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
|
|
124
|
+
yard (0.9.38) sha256=721fb82afb10532aa49860655f6cc2eaa7130889df291b052e1e6b268283010f
|
|
125
|
+
|
|
86
126
|
BUNDLED WITH
|
|
87
|
-
|
|
127
|
+
4.0.5
|
data/PLAN.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Plan: IML Gem Comprehensive Refactor
|
|
2
|
+
|
|
3
|
+
## Phase 1: Modernize Dependencies and Tooling
|
|
4
|
+
|
|
5
|
+
### Description
|
|
6
|
+
Update all dependencies to modern versions, replace Travis CI with GitHub Actions for testing, switch linting from RuboCop to StandardRB, and bump minimum Ruby version to 3.1+. This phase establishes the foundation for all subsequent changes.
|
|
7
|
+
|
|
8
|
+
### Steps
|
|
9
|
+
|
|
10
|
+
#### Step 1.1: Update Ruby Version Requirement and Gemspec
|
|
11
|
+
- **Objective**: Bump minimum Ruby to 3.1, modernize gemspec structure
|
|
12
|
+
- **Files**: `iml.gemspec`, `gemspec.yml`, `.ruby-version` (create)
|
|
13
|
+
- **Dependencies**: None
|
|
14
|
+
- **Implementation**:
|
|
15
|
+
- Set `required_ruby_version` to `>= 3.1`
|
|
16
|
+
- Update `activesupport` from `~> 5.2` to `~> 7.1`
|
|
17
|
+
- Update `bundler` dev dependency to `~> 2.4`
|
|
18
|
+
- Update `rake` to `~> 13.0`
|
|
19
|
+
- Update `rspec` to `~> 3.13`
|
|
20
|
+
- Replace `simplecov ~> 0.16` with `simplecov ~> 0.22`
|
|
21
|
+
- Remove `codeclimate-test-reporter` (deprecated)
|
|
22
|
+
- Remove `pry` dependency (use `irb` or `debug` gem instead)
|
|
23
|
+
- Remove `tqdm` dependency (replace with Ruby-native progress in CLI)
|
|
24
|
+
- Add `standard ~> 1.40` as dev dependency
|
|
25
|
+
- Create `.ruby-version` file with `3.1.0`
|
|
26
|
+
|
|
27
|
+
#### Step 1.2: Replace Travis CI with GitHub Actions
|
|
28
|
+
- **Objective**: Modern CI pipeline with matrix testing
|
|
29
|
+
- **Files**: `.github/workflows/ci.yml` (create), `.travis.yml` (delete)
|
|
30
|
+
- **Dependencies**: Step 1.1
|
|
31
|
+
- **Implementation**:
|
|
32
|
+
- Create GitHub Actions workflow for CI (Ruby 3.1, 3.2, 3.3)
|
|
33
|
+
- Run `bundle exec rspec` and `bundle exec standardrb`
|
|
34
|
+
- Remove `.travis.yml`
|
|
35
|
+
|
|
36
|
+
#### Step 1.3: Switch Linting to StandardRB
|
|
37
|
+
- **Objective**: Replace RuboCop with StandardRB for zero-config linting
|
|
38
|
+
- **Files**: `.rubocop.yml` (delete), `.standard.yml` (create)
|
|
39
|
+
- **Dependencies**: Step 1.1
|
|
40
|
+
- **Implementation**:
|
|
41
|
+
- Remove `.rubocop.yml`
|
|
42
|
+
- Create `.standard.yml` if any overrides needed
|
|
43
|
+
- Update Rakefile to include StandardRB task
|
|
44
|
+
|
|
45
|
+
#### Step 1.4: Update Gemfile and Run Bundle Install
|
|
46
|
+
- **Objective**: Lock new dependency versions
|
|
47
|
+
- **Files**: `Gemfile`, `Gemfile.lock`
|
|
48
|
+
- **Dependencies**: Steps 1.1-1.3
|
|
49
|
+
- **Implementation**:
|
|
50
|
+
- Update Gemfile if needed
|
|
51
|
+
- Run `bundle install`
|
|
52
|
+
- Verify all dependencies resolve
|
|
53
|
+
|
|
54
|
+
## Phase 2: Architecture Rewrite — Composition Over Inheritance
|
|
55
|
+
|
|
56
|
+
### Description
|
|
57
|
+
Replace OpenStruct inheritance with plain Ruby objects using composition. Eliminate `method_missing` reliance in favor of explicit interfaces. Replace `IML::Hash` with a simple configuration object. This phase fundamentally restructures the core domain model.
|
|
58
|
+
|
|
59
|
+
### Steps
|
|
60
|
+
|
|
61
|
+
#### Step 2.1: Create Configuration Module
|
|
62
|
+
- **Objective**: Replace `IML::Hash` and `IML::Patterns.config` with a proper configuration object
|
|
63
|
+
- **Files**: `lib/iml/configuration.rb` (create), `lib/iml/hash.rb` (delete)
|
|
64
|
+
- **Dependencies**: Phase 1 complete
|
|
65
|
+
- **Implementation**:
|
|
66
|
+
- Create `IML::Configuration` class that loads `patterns.yml`
|
|
67
|
+
- Use `Struct` or plain Ruby with explicit accessors instead of `HashWithIndifferentAccess`
|
|
68
|
+
- Provide `IML.configuration` singleton method
|
|
69
|
+
- Cache loaded config (load once, not on every pattern build)
|
|
70
|
+
- Remove dependency on `activesupport/core_ext/hash`
|
|
71
|
+
|
|
72
|
+
#### Step 2.2: Rewrite Pattern Builder
|
|
73
|
+
- **Objective**: Replace `method_missing`-based pattern building with explicit methods
|
|
74
|
+
- **Files**: `lib/iml/pattern_builder.rb` (create), `lib/iml/patterns.rb` (rewrite)
|
|
75
|
+
- **Dependencies**: Step 2.1
|
|
76
|
+
- **Implementation**:
|
|
77
|
+
- Create `IML::PatternBuilder` that constructs regex from config
|
|
78
|
+
- Explicit methods for each pattern component (`title_pattern`, `year_pattern`, etc.)
|
|
79
|
+
- Move pattern templates (movie/tv formats) into config or constants
|
|
80
|
+
- Remove `method_missing` / `respond_to_missing?` from patterns
|
|
81
|
+
- Return frozen Regexp objects
|
|
82
|
+
|
|
83
|
+
#### Step 2.3: Create Media Result Value Objects
|
|
84
|
+
- **Objective**: Replace OpenStruct-based Base/Movie/TVSeries with composition-based value objects
|
|
85
|
+
- **Files**: `lib/iml/media/result.rb` (create), `lib/iml/media/movie.rb` (create), `lib/iml/media/tv_series.rb` (create)
|
|
86
|
+
- **Dependencies**: Step 2.1
|
|
87
|
+
- **Implementation**:
|
|
88
|
+
- Create `IML::Media::Result` as a plain Ruby class with explicit attributes
|
|
89
|
+
- Use `Data.define` (Ruby 3.2+) or `Struct` for immutable value objects
|
|
90
|
+
- Compose with a `Formatter` for output path generation (not inherited)
|
|
91
|
+
- Compose with a `Normalizer` for codec/audio normalization
|
|
92
|
+
- `IML::Media::Movie` and `IML::Media::TvSeries` as specialized result types
|
|
93
|
+
- Remove all OpenStruct usage
|
|
94
|
+
|
|
95
|
+
#### Step 2.4: Create Formatter Service
|
|
96
|
+
- **Objective**: Extract output path formatting into a dedicated service
|
|
97
|
+
- **Files**: `lib/iml/formatter.rb` (create)
|
|
98
|
+
- **Dependencies**: Step 2.3
|
|
99
|
+
- **Implementation**:
|
|
100
|
+
- Create `IML::Formatter` that takes a result and format string
|
|
101
|
+
- `call(result, format: nil)` returns formatted string
|
|
102
|
+
- Placeholder definitions live with the formatter, not the model
|
|
103
|
+
- Support custom format strings
|
|
104
|
+
|
|
105
|
+
#### Step 2.5: Create Normalizer Service
|
|
106
|
+
- **Objective**: Extract codec/audio normalization into a dedicated service
|
|
107
|
+
- **Files**: `lib/iml/normalizer.rb` (create)
|
|
108
|
+
- **Dependencies**: Steps 2.1, 2.3
|
|
109
|
+
- **Implementation**:
|
|
110
|
+
- Create `IML::Normalizer` that normalizes codec and audio names
|
|
111
|
+
- `call(attributes)` returns normalized attribute hash
|
|
112
|
+
- Uses config for lookup tables
|
|
113
|
+
- Handles title case conversion
|
|
114
|
+
|
|
115
|
+
#### Step 2.6: Rewrite Parser (formerly Text)
|
|
116
|
+
- **Objective**: Replace `IML::Text < String` with a proper parser using composition
|
|
117
|
+
- **Files**: `lib/iml/parser.rb` (create), `lib/iml/text.rb` (delete)
|
|
118
|
+
- **Dependencies**: Steps 2.2, 2.3, 2.5
|
|
119
|
+
- **Implementation**:
|
|
120
|
+
- Create `IML::Parser` class (does not inherit from String)
|
|
121
|
+
- `parse(filename)` returns `Media::Movie`, `Media::TvSeries`, or `nil`
|
|
122
|
+
- Inject pattern builder and normalizer
|
|
123
|
+
- Clean separation: parsing, normalization, and result creation are distinct steps
|
|
124
|
+
|
|
125
|
+
#### Step 2.7: Create File Mover Service
|
|
126
|
+
- **Objective**: Extract file operations from Base into a dedicated service
|
|
127
|
+
- **Files**: `lib/iml/file_mover.rb` (create)
|
|
128
|
+
- **Dependencies**: Steps 2.3, 2.4
|
|
129
|
+
- **Implementation**:
|
|
130
|
+
- Create `IML::FileMover` service
|
|
131
|
+
- `call(source_path, result, format: nil, target: nil, pretend: false)`
|
|
132
|
+
- Handles directory creation, file moving, error handling
|
|
133
|
+
- Returns result object (success/failure) instead of integer codes
|
|
134
|
+
|
|
135
|
+
#### Step 2.8: Update Main Entry Point
|
|
136
|
+
- **Objective**: Wire up new architecture in `lib/iml.rb`
|
|
137
|
+
- **Files**: `lib/iml.rb` (rewrite)
|
|
138
|
+
- **Dependencies**: Steps 2.1-2.7
|
|
139
|
+
- **Implementation**:
|
|
140
|
+
- Remove old requires (text, base, movie, tvseries, hash)
|
|
141
|
+
- Add new requires (configuration, parser, formatter, normalizer, file_mover, media/*)
|
|
142
|
+
- Provide `IML.parse(filename)` convenience method
|
|
143
|
+
- Provide `IML.configuration` accessor
|
|
144
|
+
- Remove conditional `pry` require
|
|
145
|
+
- Remove `puts` for missing iml-imdb (use proper logging or silence)
|
|
146
|
+
|
|
147
|
+
#### Step 2.9: Delete Legacy Files
|
|
148
|
+
- **Objective**: Remove old architecture files
|
|
149
|
+
- **Files**: `lib/iml/base.rb`, `lib/iml/text.rb`, `lib/iml/movie.rb`, `lib/iml/tvseries.rb`, `lib/iml/hash.rb` (all delete)
|
|
150
|
+
- **Dependencies**: Steps 2.6-2.8
|
|
151
|
+
- **Implementation**:
|
|
152
|
+
- Delete all legacy class files
|
|
153
|
+
- Verify no remaining references
|
|
154
|
+
|
|
155
|
+
## Phase 3: CLI Modernization
|
|
156
|
+
|
|
157
|
+
### Description
|
|
158
|
+
Rewrite the CLI script to use the new architecture, add `--version` flag, remove `tqdm` dependency, and improve error handling.
|
|
159
|
+
|
|
160
|
+
### Steps
|
|
161
|
+
|
|
162
|
+
#### Step 3.1: Rewrite CLI Script
|
|
163
|
+
- **Objective**: Modern CLI using new architecture with proper structure
|
|
164
|
+
- **Files**: `bin/iml` (rewrite)
|
|
165
|
+
- **Dependencies**: Phase 2 complete
|
|
166
|
+
- **Implementation**:
|
|
167
|
+
- Add `--version` / `-V` flag (print `IML::VERSION` and exit)
|
|
168
|
+
- Replace `tqdm` progress bar with simple STDERR output or `$stderr.print`
|
|
169
|
+
- Use `IML::Parser` and `IML::FileMover` services
|
|
170
|
+
- Move `file_operations` from top-level method into a CLI class or module
|
|
171
|
+
- Proper exit codes (0 success, 1 error)
|
|
172
|
+
- Replace `Logger.new(STDOUT)` with configurable logger
|
|
173
|
+
- Handle SIGINT gracefully
|
|
174
|
+
|
|
175
|
+
## Phase 4: Remove ActiveSupport Dependency
|
|
176
|
+
|
|
177
|
+
### Description
|
|
178
|
+
Replace remaining ActiveSupport usage with lightweight Ruby equivalents to eliminate the heavy dependency.
|
|
179
|
+
|
|
180
|
+
### Steps
|
|
181
|
+
|
|
182
|
+
#### Step 4.1: Replace ActiveSupport Inflector
|
|
183
|
+
- **Objective**: Remove `titleize` dependency on ActiveSupport
|
|
184
|
+
- **Files**: `lib/iml/utils.rb` (create)
|
|
185
|
+
- **Dependencies**: Phase 2 complete
|
|
186
|
+
- **Implementation**:
|
|
187
|
+
- Create `IML::Utils.titleize(string)` — simple implementation
|
|
188
|
+
- Replace `.titleize` calls with `IML::Utils.titleize`
|
|
189
|
+
- Verify edge cases match expected behavior
|
|
190
|
+
|
|
191
|
+
#### Step 4.2: Remove HashWithIndifferentAccess Usage
|
|
192
|
+
- **Objective**: Eliminate remaining ActiveSupport hash dependency
|
|
193
|
+
- **Files**: Various (already handled in Phase 2 config rewrite)
|
|
194
|
+
- **Dependencies**: Step 2.1
|
|
195
|
+
- **Implementation**:
|
|
196
|
+
- Verify `IML::Configuration` uses plain Ruby hashes with string keys
|
|
197
|
+
- Use `transform_keys(&:to_s)` or `symbolize_keys` as needed
|
|
198
|
+
- Remove `require 'active_support/core_ext/hash'`
|
|
199
|
+
|
|
200
|
+
#### Step 4.3: Remove ActiveSupport from Gemspec
|
|
201
|
+
- **Objective**: Drop the activesupport runtime dependency entirely
|
|
202
|
+
- **Files**: `gemspec.yml`, `lib/iml.rb`
|
|
203
|
+
- **Dependencies**: Steps 4.1-4.2
|
|
204
|
+
- **Implementation**:
|
|
205
|
+
- Remove `activesupport` from dependencies in `gemspec.yml`
|
|
206
|
+
- Remove all `require 'active_support/*'` lines
|
|
207
|
+
- Run tests to verify nothing breaks
|
|
208
|
+
|
|
209
|
+
## Phase 5: Comprehensive Test Suite
|
|
210
|
+
|
|
211
|
+
### Description
|
|
212
|
+
Rewrite the test suite to match the new architecture with thorough coverage, proper organization, and `:verified` tags.
|
|
213
|
+
|
|
214
|
+
### Steps
|
|
215
|
+
|
|
216
|
+
#### Step 5.1: Set Up Test Infrastructure
|
|
217
|
+
- **Objective**: Modern RSpec configuration with proper helpers
|
|
218
|
+
- **Files**: `spec/spec_helper.rb` (rewrite), `.rspec` (update)
|
|
219
|
+
- **Dependencies**: Phase 2 complete
|
|
220
|
+
- **Implementation**:
|
|
221
|
+
- Configure SimpleCov with minimum coverage threshold
|
|
222
|
+
- Add `:verified` tag filtering
|
|
223
|
+
- Set up shared contexts for common test data
|
|
224
|
+
- Create `spec/support/` directory for shared examples
|
|
225
|
+
|
|
226
|
+
#### Step 5.2: Test Configuration
|
|
227
|
+
- **Objective**: Full coverage of pattern configuration loading
|
|
228
|
+
- **Files**: `spec/configuration_spec.rb` (create)
|
|
229
|
+
- **Dependencies**: Step 5.1
|
|
230
|
+
- **Implementation**:
|
|
231
|
+
- Test config loads from YAML
|
|
232
|
+
- Test all config keys accessible
|
|
233
|
+
- Test caching behavior
|
|
234
|
+
- Test with missing/malformed config file
|
|
235
|
+
|
|
236
|
+
#### Step 5.3: Test Pattern Builder
|
|
237
|
+
- **Objective**: Full coverage of regex pattern construction
|
|
238
|
+
- **Files**: `spec/pattern_builder_spec.rb` (create)
|
|
239
|
+
- **Dependencies**: Step 5.1
|
|
240
|
+
- **Implementation**:
|
|
241
|
+
- Test each pattern component generates valid regex
|
|
242
|
+
- Test movie patterns match expected filenames
|
|
243
|
+
- Test TV patterns match expected filenames
|
|
244
|
+
- Test patterns reject non-matching filenames
|
|
245
|
+
- Edge cases: special characters, unusual formats
|
|
246
|
+
|
|
247
|
+
#### Step 5.4: Test Parser
|
|
248
|
+
- **Objective**: Comprehensive filename parsing tests
|
|
249
|
+
- **Files**: `spec/parser_spec.rb` (create)
|
|
250
|
+
- **Dependencies**: Step 5.1
|
|
251
|
+
- **Implementation**:
|
|
252
|
+
- Test movie detection with various formats
|
|
253
|
+
- Test TV series detection with various formats
|
|
254
|
+
- Test unrecognized filenames return nil
|
|
255
|
+
- Test edge cases: missing fields, unusual separators, 4K content
|
|
256
|
+
- Test with real-world filename examples
|
|
257
|
+
|
|
258
|
+
#### Step 5.5: Test Media Result Objects
|
|
259
|
+
- **Objective**: Full coverage of value objects
|
|
260
|
+
- **Files**: `spec/media/movie_spec.rb` (create), `spec/media/tv_series_spec.rb` (create)
|
|
261
|
+
- **Dependencies**: Step 5.1
|
|
262
|
+
- **Implementation**:
|
|
263
|
+
- Test attribute access
|
|
264
|
+
- Test immutability (if using Data.define)
|
|
265
|
+
- Test type predicates (`movie?`, `tv?`)
|
|
266
|
+
- Test season_i / episode_i for TV series
|
|
267
|
+
|
|
268
|
+
#### Step 5.6: Test Formatter
|
|
269
|
+
- **Objective**: Full coverage of output path formatting
|
|
270
|
+
- **Files**: `spec/formatter_spec.rb` (create)
|
|
271
|
+
- **Dependencies**: Step 5.1
|
|
272
|
+
- **Implementation**:
|
|
273
|
+
- Test default format strings for movie and TV
|
|
274
|
+
- Test custom format strings
|
|
275
|
+
- Test all placeholder substitutions
|
|
276
|
+
- Test with missing attributes (graceful handling)
|
|
277
|
+
|
|
278
|
+
#### Step 5.7: Test Normalizer
|
|
279
|
+
- **Objective**: Full coverage of codec/audio normalization
|
|
280
|
+
- **Files**: `spec/normalizer_spec.rb` (create)
|
|
281
|
+
- **Dependencies**: Step 5.1
|
|
282
|
+
- **Implementation**:
|
|
283
|
+
- Test video codec normalization (x264 -> h.264, etc.)
|
|
284
|
+
- Test audio codec normalization with channels
|
|
285
|
+
- Test title case conversion
|
|
286
|
+
- Test unknown codecs pass through unchanged
|
|
287
|
+
|
|
288
|
+
#### Step 5.8: Test File Mover
|
|
289
|
+
- **Objective**: Full coverage of file operations
|
|
290
|
+
- **Files**: `spec/file_mover_spec.rb` (create)
|
|
291
|
+
- **Dependencies**: Step 5.1
|
|
292
|
+
- **Implementation**:
|
|
293
|
+
- Test directory creation
|
|
294
|
+
- Test file moving
|
|
295
|
+
- Test pretend mode (no actual operations)
|
|
296
|
+
- Test error handling (missing source, permission errors)
|
|
297
|
+
- Use tmpdir for actual file operations
|
|
298
|
+
|
|
299
|
+
#### Step 5.9: Delete Legacy Tests
|
|
300
|
+
- **Objective**: Remove old test file
|
|
301
|
+
- **Files**: `spec/iml_spec.rb` (delete)
|
|
302
|
+
- **Dependencies**: Steps 5.2-5.8
|
|
303
|
+
- **Implementation**:
|
|
304
|
+
- Delete monolithic test file
|
|
305
|
+
- Verify all test scenarios covered by new specs
|
|
306
|
+
- Run full suite to confirm green
|
|
307
|
+
|
|
308
|
+
## Phase 6: Final Cleanup and Verification
|
|
309
|
+
|
|
310
|
+
### Description
|
|
311
|
+
Run all linters and tests, verify the gem builds, update documentation, and ensure everything is release-ready.
|
|
312
|
+
|
|
313
|
+
### Steps
|
|
314
|
+
|
|
315
|
+
#### Step 6.1: Run StandardRB and Fix Issues
|
|
316
|
+
- **Objective**: Zero linting warnings
|
|
317
|
+
- **Files**: Various (auto-fix)
|
|
318
|
+
- **Dependencies**: Phases 1-5 complete
|
|
319
|
+
- **Implementation**:
|
|
320
|
+
- Run `bundle exec standardrb --fix .`
|
|
321
|
+
- Review and manually fix any remaining issues
|
|
322
|
+
- Ensure all files have `frozen_string_literal: true`
|
|
323
|
+
|
|
324
|
+
#### Step 6.2: Run Full Test Suite
|
|
325
|
+
- **Objective**: All tests pass with good coverage
|
|
326
|
+
- **Files**: None (verification only)
|
|
327
|
+
- **Dependencies**: Step 6.1
|
|
328
|
+
- **Implementation**:
|
|
329
|
+
- Run `bundle exec rspec`
|
|
330
|
+
- Verify coverage meets threshold
|
|
331
|
+
- Fix any failures
|
|
332
|
+
|
|
333
|
+
#### Step 6.3: Build and Verify Gem
|
|
334
|
+
- **Objective**: Gem builds cleanly
|
|
335
|
+
- **Files**: None (verification only)
|
|
336
|
+
- **Dependencies**: Step 6.2
|
|
337
|
+
- **Implementation**:
|
|
338
|
+
- Run `gem build iml.gemspec`
|
|
339
|
+
- Verify gem file contents are correct
|
|
340
|
+
- Test `gem install` locally
|
|
341
|
+
|
|
342
|
+
#### Step 6.4: Update README
|
|
343
|
+
- **Objective**: Documentation reflects new architecture and usage
|
|
344
|
+
- **Files**: `README.md`
|
|
345
|
+
- **Dependencies**: Step 6.2
|
|
346
|
+
- **Implementation**:
|
|
347
|
+
- Update usage examples to new API (`IML.parse`)
|
|
348
|
+
- Update dependency requirements (Ruby 3.1+)
|
|
349
|
+
- Document new CLI flags (`--version`)
|
|
350
|
+
- Remove references to ActiveSupport
|