tarquinn 0.2.0 → 0.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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +16 -10
  3. data/.github/copilot-instructions.md +188 -0
  4. data/.gitignore +9 -0
  5. data/.rubocop.yml +29 -0
  6. data/.rubocop_todo.yml +13 -0
  7. data/Dockerfile +2 -2
  8. data/Gemfile +15 -0
  9. data/Makefile +21 -0
  10. data/README.md +110 -3
  11. data/Rakefile +5 -0
  12. data/config/check_specs.yml +4 -0
  13. data/config/rubycritc.rb +12 -0
  14. data/config/yardstick.rb +13 -0
  15. data/config/yardstick.yml +55 -0
  16. data/docker-compose.yml +1 -1
  17. data/lib/tarquinn/class_methods.rb +132 -12
  18. data/lib/tarquinn/condition/action_checker.rb +45 -7
  19. data/lib/tarquinn/condition/method_caller.rb +46 -8
  20. data/lib/tarquinn/condition/proc_runner.rb +36 -7
  21. data/lib/tarquinn/condition.rb +65 -4
  22. data/lib/tarquinn/controller.rb +59 -13
  23. data/lib/tarquinn/exception.rb +20 -0
  24. data/lib/tarquinn/redirection_config/options.rb +58 -0
  25. data/lib/tarquinn/redirection_config.rb +175 -0
  26. data/lib/tarquinn/redirection_config_builder.rb +88 -0
  27. data/lib/tarquinn/redirection_handler.rb +194 -0
  28. data/lib/tarquinn/request_handler.rb +89 -0
  29. data/lib/tarquinn/request_handler_builder.rb +90 -0
  30. data/lib/tarquinn/version.rb +6 -1
  31. data/lib/tarquinn.rb +97 -8
  32. data/spec/dummy/Rakefile +8 -0
  33. data/spec/dummy/app/assets/images/.keep +0 -0
  34. data/spec/dummy/app/assets/stylesheets/application.css +1 -0
  35. data/spec/dummy/app/channels/application_cable/channel.rb +6 -0
  36. data/spec/dummy/app/channels/application_cable/connection.rb +6 -0
  37. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  38. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  39. data/spec/dummy/app/controllers/tarquinn/dummy_controller.rb +43 -0
  40. data/spec/dummy/app/controllers/tarquinn/dummy_route_controller.rb +37 -0
  41. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  42. data/spec/dummy/app/jobs/application_job.rb +9 -0
  43. data/spec/dummy/app/mailers/application_mailer.rb +6 -0
  44. data/spec/dummy/app/models/application_record.rb +5 -0
  45. data/spec/dummy/app/models/concerns/.keep +0 -0
  46. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  47. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  48. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  49. data/spec/dummy/app/views/tarquinn/dummy_route/index.html +0 -0
  50. data/spec/dummy/app/views/tarquinn/dummy_route/new.html +0 -0
  51. data/spec/dummy/bin/rails +6 -0
  52. data/spec/dummy/bin/rake +6 -0
  53. data/spec/dummy/bin/setup +35 -0
  54. data/spec/dummy/config/application.rb +24 -0
  55. data/spec/dummy/config/boot.rb +7 -0
  56. data/spec/dummy/config/cable.yml +10 -0
  57. data/spec/dummy/config/database.yml +25 -0
  58. data/spec/dummy/config/environment.rb +7 -0
  59. data/spec/dummy/config/environments/development.rb +69 -0
  60. data/spec/dummy/config/environments/production.rb +89 -0
  61. data/spec/dummy/config/environments/test.rb +62 -0
  62. data/spec/dummy/config/initializers/content_security_policy.rb +26 -0
  63. data/spec/dummy/config/initializers/filter_parameter_logging.rb +10 -0
  64. data/spec/dummy/config/initializers/inflections.rb +17 -0
  65. data/spec/dummy/config/initializers/permissions_policy.rb +12 -0
  66. data/spec/dummy/config/locales/en.yml +33 -0
  67. data/spec/dummy/config/puma.rb +45 -0
  68. data/spec/dummy/config/routes.rb +8 -0
  69. data/spec/dummy/config/storage.yml +34 -0
  70. data/spec/dummy/config.ru +8 -0
  71. data/spec/dummy/db/schema.rb +16 -0
  72. data/spec/dummy/lib/assets/.keep +0 -0
  73. data/spec/dummy/log/.keep +0 -0
  74. data/spec/dummy/public/404.html +67 -0
  75. data/spec/dummy/public/422.html +67 -0
  76. data/spec/dummy/public/500.html +66 -0
  77. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  78. data/spec/dummy/public/apple-touch-icon.png +0 -0
  79. data/spec/dummy/public/favicon.ico +0 -0
  80. data/spec/dummy/storage/.keep +0 -0
  81. data/spec/dummy/tmp/.keep +0 -0
  82. data/spec/dummy/tmp/pids/.keep +0 -0
  83. data/spec/dummy/tmp/storage/.keep +0 -0
  84. data/spec/lib/tarquinn/condition/action_checker_spec.rb +4 -2
  85. data/spec/lib/tarquinn/condition/method_caller_spec.rb +5 -3
  86. data/spec/lib/tarquinn/condition/proc_runner_spec.rb +56 -4
  87. data/spec/lib/tarquinn/condition_spec.rb +53 -0
  88. data/spec/lib/tarquinn/controller_spec.rb +83 -10
  89. data/spec/lib/tarquinn/exception/redirection_already_defined_spec.rb +13 -0
  90. data/spec/lib/tarquinn/redirection_config/options_spec.rb +45 -0
  91. data/spec/lib/tarquinn/redirection_config_builder_spec.rb +57 -0
  92. data/spec/lib/tarquinn/{config_spec.rb → redirection_config_spec.rb} +4 -2
  93. data/spec/lib/tarquinn/{handler_spec.rb → redirection_handler_spec.rb} +42 -5
  94. data/spec/lib/tarquinn/request_handler_builder_spec.rb +45 -0
  95. data/spec/lib/tarquinn/{engine_spec.rb → request_handler_spec.rb} +5 -3
  96. data/spec/lib/tarquinn_spec.rb +202 -13
  97. data/spec/spec_helper.rb +16 -6
  98. data/spec/support/shared_examples/config.rb +4 -2
  99. data/tarquinn.gemspec +10 -13
  100. metadata +87 -92
  101. data/lib/tarquinn/builder.rb +0 -28
  102. data/lib/tarquinn/concern.rb +0 -17
  103. data/lib/tarquinn/config.rb +0 -39
  104. data/lib/tarquinn/engine.rb +0 -31
  105. data/lib/tarquinn/handler.rb +0 -49
  106. data/spec/lib/tarquinn/builder_spec.rb +0 -13
  107. data/spec/support/models/tarquinn/dummy_controller.rb +0 -43
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b942f4c6eef09e4a94c12a33da00f6c878ebeb30d348dc06dad7aa2274d635b9
4
- data.tar.gz: b80da172aef6a2067b97444c53842bed6215afbbba5d885793376f8f8ff8f6a6
3
+ metadata.gz: 472e75e26a2d619f0284c9eb797c5e47f717a9f9a6e52757fc1c5ad7272a174f
4
+ data.tar.gz: efb31ef0021491a3b99c48cb8c3a34026493a10500636449195c1070d281dc91
5
5
  SHA512:
6
- metadata.gz: cbb0a21142829270e9ac2590ff071ed5dfada57c2bf6ba116543b9c8c735eb88f8170a6550b3badbc56506dbae2dfc109f76c88c7e40efaa90c94a3b3bb61629
7
- data.tar.gz: 1b7fe947a50f0ee13e0ef2cdd1842b18f19af51c347d494442f34abf2eb4195f5335fcbdec8794933465652af544fa463b8d3846a49ff4c12835d17ace565d03
6
+ metadata.gz: 9391c038495ea739fee48b43a9c104bcb0dfb887aa87ecb75be3d1378ee2c11649cc68725fd8beea215036065b5deb1aeca08babea956d77b42628b887ead261
7
+ data.tar.gz: 59ccde1cade0e2b76b82f89073409cf9ced274d7346214ae08f2d4e6f06e11269feb9b768c219064bcec0e748205c1ce6a5eb45515e21dbe404a53459cb6643b
data/.circleci/config.yml CHANGED
@@ -18,30 +18,24 @@ workflows:
18
18
  only: /\d+\.\d+\.\d+/
19
19
  branches:
20
20
  only:
21
- - master
21
+ - main
22
22
  jobs:
23
23
  test:
24
24
  docker:
25
- - image: darthjee/circleci_rails_gems:0.6.2
25
+ - image: darthjee/circleci_ruby_331:1.0.1
26
26
  environment:
27
27
  PROJECT: tarquinn
28
28
  steps:
29
29
  - checkout
30
- - run:
31
- name: Prepare Coverage Test Report
32
- command: cc-test-reporter before-build
33
30
  - run:
34
31
  name: Bundle Install
35
32
  command: bundle install
36
33
  - run:
37
34
  name: RSpec
38
35
  command: bundle exec rspec
39
- - run:
40
- name: Coverage Test Report
41
- command: cc-test-reporter after-build --exit-code $?
42
36
  checks:
43
37
  docker:
44
- - image: darthjee/circleci_rails_gems:0.6.2
38
+ - image: darthjee/circleci_ruby_331:1.0.1
45
39
  environment:
46
40
  PROJECT: tarquinn
47
41
  steps:
@@ -49,12 +43,24 @@ jobs:
49
43
  - run:
50
44
  name: Bundle Install
51
45
  command: bundle install
46
+ - run:
47
+ name: Rubocop
48
+ command: rubocop
49
+ - run:
50
+ name: Yardstick coverage check
51
+ command: bundle exec rake verify_measurements
52
52
  - run:
53
53
  name: Check version documentation
54
54
  command: check_readme.sh
55
+ - run:
56
+ name: Rubycritcs check
57
+ command: rubycritic.sh
58
+ - run:
59
+ name: Check unit tests
60
+ command: check_specs
55
61
  build-and-release:
56
62
  docker:
57
- - image: darthjee/circleci_rails_gems:0.6.2
63
+ - image: darthjee/circleci_ruby_331:1.0.1
58
64
  environment:
59
65
  PROJECT: tarquinn
60
66
  steps:
@@ -0,0 +1,188 @@
1
+ # GitHub Copilot Instructions for Tarquinn
2
+
3
+ ## Project Overview
4
+
5
+ Tarquinn is a Ruby gem that provides generic redirection control for Rails controllers.
6
+ It is implemented as an `ActiveSupport::Concern` that adds `before_action` hooks and
7
+ class-level DSL methods (`redirection_rule`, `skip_redirection`, `skip_redirection_rule`)
8
+ to any Rails controller.
9
+
10
+ Key components:
11
+
12
+ - **`Tarquinn`** – The main concern included in controllers; sets up `before_action :perform_redirection`.
13
+ - **`Tarquinn::ClassMethods`** – DSL methods added to controller classes.
14
+ - **`Tarquinn::RequestHandlerBuilder`** – Accumulates redirection configurations for a controller class.
15
+ - **`Tarquinn::RequestHandler`** – Processes a single request, iterating over configs to find the first matching redirect.
16
+ - **`Tarquinn::RedirectionHandler`** – Evaluates one redirection config (conditions + skip rules) for a request.
17
+ - **`Tarquinn::RedirectionConfig`** – Holds the data for a single redirection rule (blocks, skip blocks, redirect target).
18
+ - **`Tarquinn::Condition`** – Wraps a single condition (method name or block) used in redirection/skip evaluation.
19
+ - **`Tarquinn::Controller`** – Thin wrapper around the Rails controller instance, used by handlers.
20
+
21
+ ## Redirection Rules Data Flow
22
+
23
+ ### How It Works
24
+
25
+ 1. A controller includes `Tarquinn` (an `ActiveSupport::Concern`), which:
26
+ - Extends the controller with `Tarquinn::ClassMethods`, making the DSL methods available.
27
+ - Registers a `before_action :perform_redirection` that runs on every request.
28
+
29
+ 2. During a request, `perform_redirection` delegates to `Tarquinn::RequestHandler`, which
30
+ iterates over all registered `Tarquinn::RedirectionConfig` objects (in definition order)
31
+ and applies the **first** rule whose conditions are satisfied.
32
+
33
+ 3. Each rule is evaluated by `Tarquinn::RedirectionHandler`:
34
+ - All condition methods and/or the optional block are evaluated against the current
35
+ controller instance.
36
+ - If **any** condition returns a truthy value the rule fires and the controller redirects
37
+ to the path returned by the rule's target method.
38
+ - Skip conditions (registered via `skip_redirection` or `skip_redirection_rule`) are
39
+ checked first; if any skip condition is truthy the rule is bypassed entirely.
40
+
41
+ ### Defining a Redirection Rule — `redirection_rule`
42
+
43
+ ```ruby
44
+ redirection_rule <rule_name>, *<condition_methods>, &<block>
45
+ ```
46
+
47
+ | Argument | Description |
48
+ |---------------------|----------------------------------------------------------------------------------------------|
49
+ | `rule_name` | Symbol. Also the name of the controller method that returns the redirect path. |
50
+ | `condition_methods` | Zero or more symbol method names. Each is called on the controller; truthy → rule fires. |
51
+ | `block` | Optional. Evaluated in the context of the controller; truthy → rule fires. |
52
+
53
+ **Evaluation**: the rule fires when **any** condition method **or** the block returns truthy.
54
+
55
+ #### Example 1 — block-based rule
56
+
57
+ ```ruby
58
+ redirection_rule :redirect_home { params[:secret_key] != '12345' }
59
+
60
+ def redirect_home
61
+ home_path
62
+ end
63
+ ```
64
+
65
+ Redirects to `home_path` if `secret_key` is absent or different from `'12345'`.
66
+
67
+ #### Example 2 — method-based rule
68
+
69
+ ```ruby
70
+ redirection_rule :redirect_home, :misses_secret_key
71
+
72
+ def redirect_home
73
+ home_path
74
+ end
75
+
76
+ def misses_secret_key
77
+ params[:secret_key] != '12345'
78
+ end
79
+ ```
80
+
81
+ Same behaviour as Example 1, but the condition is extracted into a dedicated method.
82
+
83
+ ### Skipping a Rule for Specific Actions — `skip_redirection`
84
+
85
+ ```ruby
86
+ skip_redirection <rule_name>, *<actions>
87
+ ```
88
+
89
+ Prevents the named rule from running for the listed controller actions.
90
+
91
+ ```ruby
92
+ skip_redirection :redirect_home, :index
93
+ ```
94
+
95
+ The `index` action is not affected by the `redirect_home` rule; all other actions still are.
96
+
97
+ ### Skipping a Rule Under a Condition — `skip_redirection_rule`
98
+
99
+ ```ruby
100
+ skip_redirection_rule <rule_name>, *<condition_methods>, &<block>
101
+ ```
102
+
103
+ Registers a skip condition for a rule. When the condition is truthy the rule is bypassed,
104
+ regardless of the action.
105
+
106
+ ```ruby
107
+ skip_redirection_rule :redirect_home { params[:admin_key] == '9999' }
108
+ ```
109
+
110
+ The `redirect_home` rule does not fire when the correct admin key is provided.
111
+
112
+ ### Passing Options to Redirection Rules
113
+
114
+ You can pass options to `redirection_rule` to control advanced behavior. Currently, the main supported option is `domain`, which enables cross-domain redirection.
115
+
116
+ | Option | Description |
117
+ |----------|---------------------------------------------------------------------------------------------|
118
+ | `domain` | String. If set, allows redirection to the specified domain (cross-domain). If not set, only same-host redirection is allowed. |
119
+
120
+ #### Example — domain-based rule
121
+
122
+ ```ruby
123
+ redirection_rule :redirect_external, domain: 'example.com' do
124
+ params[:should_redirect]
125
+ end
126
+
127
+ def redirect_external
128
+ '/external_path'
129
+ end
130
+ ```
131
+
132
+ This will only allow redirection to `https://example.com/external_path` because the domain option is set to `'example.com'`.
133
+
134
+ ## Language
135
+
136
+ All code, comments, documentation, commit messages, and PR descriptions must be written in **English**.
137
+
138
+ ## Coding Standards
139
+
140
+ ### General Style
141
+
142
+ - Follow the existing RuboCop configuration (`.rubocop.yml` / `.rubocop_todo.yml`).
143
+ - Use `# frozen_string_literal: true` at the top of every Ruby file.
144
+ - Keep methods small and focused (Sandi Metz style): aim for methods under 5 lines.
145
+ - Keep classes small with clear, single responsibilities and explicit object boundaries.
146
+ - Avoid deeply nested conditionals; extract guard clauses or helper methods.
147
+ - Use `private` / `attr_reader` to hide implementation details.
148
+ - Use `delegate` (ActiveSupport) instead of manual forwarding where it improves readability.
149
+
150
+ ### Documentation
151
+
152
+ - Add **YARD** documentation to all public classes, modules, and methods.
153
+ - Non-obvious private methods should also have short YARD comments.
154
+ - Always include `@param`, `@return`, and `@api public` / `@api private` tags where applicable.
155
+ - Ensure documentation coverage stays at or above the threshold in `config/yardstick.yml`.
156
+
157
+ ### Tests
158
+
159
+ - Write **RSpec** tests using the patterns established in `spec/`.
160
+ - Keep tests small and focused — one behaviour per example.
161
+ - Use `let` definitions that are **reusable** and **avoid duplication** across contexts.
162
+ - Prefer `context` blocks to describe different input/state scenarios.
163
+ - Avoid `before` blocks that do more than one thing; split them if needed.
164
+ - Use `shared_examples` or `shared_context` when the same setup appears in multiple groups.
165
+
166
+ ## CI Checks
167
+
168
+ The CI pipeline (`.circleci/config.yml`) runs the following checks on every push.
169
+ Reproduce them locally before opening a PR:
170
+
171
+ | CI Step | Local Command |
172
+ |-------------------------------|--------------------------------------------------|
173
+ | Run tests | `bundle exec rspec` |
174
+ | RuboCop lint | `bundle exec rubocop` |
175
+ | YARD documentation coverage | `bundle exec rake verify_measurements` |
176
+ | RubyCritic quality check | `rubycritic.sh` (or `bundle exec rubycritic`) |
177
+
178
+ All checks must pass before a PR can be merged.
179
+
180
+ ## Docker / Local Development
181
+
182
+ To run the project locally, use the Makefile targets:
183
+
184
+ - Build Docker image: `make build`
185
+ - Start development environment: `make dev`
186
+ - Run tests: `make tests`
187
+
188
+ See the [Developer Guide](../README.md#developer-guide) in the README for further instructions.
data/.gitignore CHANGED
@@ -1,3 +1,12 @@
1
1
  /coverage
2
2
  /pkg
3
3
  Gemfile.lock
4
+ **/*.swp
5
+ **/*.swo
6
+ spec/dummy/log/*
7
+ spec/dummy/tmp/*
8
+ **/*.sqlite3
9
+ doc
10
+ .yardoc
11
+ measurement
12
+ rubycritic
data/.rubocop.yml ADDED
@@ -0,0 +1,29 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 3.3
5
+ NewCops: enable
6
+
7
+ Lint/BooleanSymbol:
8
+ Enabled: false
9
+
10
+ Lint/EmptyBlock:
11
+ Exclude:
12
+ - spec/dummy/db/schema.rb
13
+
14
+ Metrics/BlockLength:
15
+ Exclude:
16
+ - spec/**/*_spec.rb
17
+
18
+ Lint/MissingSuper:
19
+ Enabled: false
20
+
21
+ Lint/ScriptPermission:
22
+ Exclude:
23
+ - spec/dummy/bin/*
24
+
25
+ Naming/BlockForwarding:
26
+ Enabled: false
27
+
28
+ Style/ArgumentsForwarding:
29
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,13 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2024-07-10 16:10:57 UTC using RuboCop version 1.59.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 9
10
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
11
+ # AllowedMethods: refine
12
+ Metrics/BlockLength:
13
+ Max: 87
data/Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
- FROM darthjee/scripts:0.1.8 as scripts
1
+ FROM darthjee/scripts:0.6.0 as scripts
2
2
 
3
- FROM darthjee/rails_gems:0.6.2 as base
3
+ FROM darthjee/ruby_331:1.0.1 as base
4
4
 
5
5
  COPY --chown=app:app ./ /home/app/app/
6
6
 
data/Gemfile CHANGED
@@ -1,3 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
5
+ gem 'bundler', '~> 2.5.13'
6
+ gem 'pry', '~> 0.14.2'
7
+ gem 'pry-nav', '~> 1.0.0'
8
+ gem 'rails', '7.2.3'
9
+ gem 'rake', '~> 13.1.0'
10
+ gem 'rspec', '~> 3.12.0'
11
+ gem 'rspec-rails', '6.1.1'
12
+ gem 'rubycritic', '4.9.1'
13
+ gem 'simplecov', '~> 0.22.0'
14
+ gem 'sqlite3', '1.4.2'
15
+ gem 'yard', '0.9.38'
16
+ gem 'yardstick', '0.9.9'
17
+
3
18
  gemspec
data/Makefile ADDED
@@ -0,0 +1,21 @@
1
+ .PHONY: build dev tests
2
+
3
+ PROJECT?=tarquinn
4
+ IMAGE?=$(PROJECT)
5
+ BASE_IMAGE?=$(DOCKER_ID_USER)/$(PROJECT)-base
6
+ DOCKER_FILE_BASE=Dockerfile.$(PROJECT)-base
7
+
8
+ all:
9
+ @echo "Usage:"
10
+ @echo " make build\n Build docker image for $(PROJECT)"
11
+ @echo " make dev\n Run development environment for $(PROJECT)"
12
+ @echo " make tests\n Run tests for $(PROJECT)"
13
+
14
+ build:
15
+ docker build -f Dockerfile.$(PROJECT) . -t $(IMAGE) -t $(PUSH_IMAGE):latest
16
+
17
+ tests:
18
+ docker-compose run $(PROJECT)_tests /bin/bash
19
+
20
+ dev:
21
+ docker-compose run $(PROJECT) /bin/bash
data/README.md CHANGED
@@ -2,8 +2,6 @@ Tarquinn
2
2
  ========
3
3
  [![Build Status](https://circleci.com/gh/darthjee/tarquinn.svg?style=shield)](https://circleci.com/gh/darthjee/tarquinn)
4
4
  [![Code Climate](https://codeclimate.com/github/darthjee/tarquinn/badges/gpa.svg)](https://codeclimate.com/github/darthjee/tarquinn)
5
- [![Test Coverage](https://codeclimate.com/github/darthjee/tarquinn/badges/coverage.svg)](https://codeclimate.com/github/darthjee/tarquinn/coverage)
6
- [![Issue Count](https://codeclimate.com/github/darthjee/tarquinn/badges/issue_count.svg)](https://codeclimate.com/github/darthjee/tarquinn)
7
5
  [![Gem Version](https://badge.fury.io/rb/tarquinn.svg)](https://badge.fury.io/rb/tarquinn)
8
6
  [![Inline docs](http://inch-ci.org/github/darthjee/tarquinn.svg)](http://inch-ci.org/github/darthjee/tarquinn)
9
7
 
@@ -11,10 +9,14 @@ Tarquinn
11
9
 
12
10
  Yard Documentation
13
11
  -------------------
14
- [https://www.rubydoc.info/gems/tarquinn/0.2.0](https://www.rubydoc.info/gems/tarquinn/0.2.0)
12
+ [https://www.rubydoc.info/gems/tarquinn/0.4.0](https://www.rubydoc.info/gems/tarquinn/0.4.0)
15
13
 
16
14
  This gem makes easier to controll generic redirection
17
15
 
16
+ Current Release: [0.4.0](https://github.com/darthjee/tarquinn/tree/0.4.0)
17
+
18
+ Next Version [0.4.1](https://github.com/darthjee/tarquinn/compare/0.4.0...main)
19
+
18
20
  Getting started
19
21
  ---------------
20
22
  1. Add Tarquinn to your `Gemfile` and `bundle install`:
@@ -56,3 +58,108 @@ Getting started
56
58
  end
57
59
  end
58
60
  ```
61
+
62
+ ---
63
+
64
+ ## Developer Guide
65
+
66
+ ### How It Works
67
+
68
+ Tarquinn is a Rails concern that adds a `before_action` to any controller it is included in.
69
+ On each request the action chain works as follows:
70
+
71
+ 1. `before_action :perform_redirection` is triggered automatically.
72
+ 2. A `RequestHandlerBuilder` (stored per controller class) holds all registered redirection
73
+ configs (`redirection_rule` / `skip_redirection` / `skip_redirection_rule` calls).
74
+ 3. At request time, `RequestHandlerBuilder` creates a `RequestHandler` for the current request.
75
+ 4. `RequestHandler` iterates over every `RedirectionConfig` and checks whether a redirect
76
+ should fire via `RedirectionHandler`.
77
+ 5. `RedirectionHandler` evaluates skip conditions first; if none match, it evaluates redirect
78
+ conditions. The first config that requires a redirect triggers `redirect_to`.
79
+
80
+ ### Running Locally with Docker Compose
81
+
82
+ > Prerequisites: Docker and Docker Compose installed.
83
+
84
+ **Build the image**
85
+
86
+ ```bash
87
+ docker compose build base_build
88
+ # or
89
+ ### Running Locally with Docker Compose and Makefile
90
+
91
+ | `make build` | Build the Docker image |
92
+
93
+ | `make dev` | Open an interactive bash shell inside the container |
94
+
95
+ | `make test` | Run RSpec tests inside the container |
96
+ make build
97
+ ```
98
+
99
+ **Run the test suite**
100
+
101
+ ```bash
102
+ make tests
103
+ ```
104
+
105
+ **Open an interactive shell inside the container**
106
+
107
+ ```bash
108
+ make dev
109
+ ```
110
+
111
+ ### Makefile Targets
112
+
113
+ | Target | Description |
114
+ |--------------|---------------------------------------------|
115
+ | `make build` | Build Docker image for the project |
116
+ | `make dev` | Run development environment (bash shell) |
117
+ | `make tests` | Run tests (RSpec) in the container |
118
+
119
+ ### CI Checks
120
+
121
+ The CircleCI pipeline (`.circleci/config.yml`) runs three jobs:
122
+
123
+ | Job | What it does |
124
+ |-----------------------|------------------------------------------------------------------------------------------|
125
+ | `test` | `bundle exec rspec` + uploads coverage report |
126
+ | `checks` | RuboCop, Yardstick coverage, README version check, RubyCritic, unit-test structure check |
127
+ | `build-and-release` | Builds and pushes the gem (tags only, on `master`) |
128
+
129
+ Run the same checks locally before opening a PR:
130
+
131
+ ```bash
132
+ # Tests
133
+ bundle exec rspec
134
+
135
+ # RuboCop
136
+ bundle exec rubocop
137
+
138
+ # YARD documentation coverage
139
+ bundle exec rake verify_measurements
140
+ ```
141
+
142
+ ### Domain Option for Cross-Domain Redirection
143
+
144
+ You can specify a `domain` option in your `redirection_rule` to allow cross-domain redirection. When set, the redirection will be allowed to external hosts and the specified domain will be used for validation.
145
+
146
+ **Example:**
147
+
148
+ ```ruby
149
+ class ExternalRedirectController < ApplicationController
150
+ include Tarquinn
151
+
152
+ redirection_rule :redirect_external, domain: 'example.com' do
153
+ params[:should_redirect]
154
+ end
155
+
156
+ private
157
+
158
+ def redirect_external
159
+ '/external_path'
160
+ end
161
+ end
162
+ ```
163
+
164
+ - If `domain` is not set, redirection is only allowed for the same host.
165
+ - If `domain` is set, redirection to the specified domain is allowed.
data/Rakefile CHANGED
@@ -1,5 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
5
+ require 'yardstick/rake/measurement'
6
+ require './config/yardstick'
7
+ require './config/rubycritc'
3
8
 
4
9
  RSpec::Core::RakeTask.new
5
10
 
@@ -0,0 +1,4 @@
1
+ ignore:
2
+ - lib/tarquinn/class_methods.rb
3
+ - lib/tarquinn/version.rb
4
+ - lib/tarquinn/exception.rb
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubycritic/rake_task'
4
+
5
+ RubyCritic::RakeTask.new do |task|
6
+ options = %w[
7
+ --path rubycritic/
8
+ --no-browser
9
+ ]
10
+ task.options = options.join(' ')
11
+ task.paths = %w[lib]
12
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yardstick/rake/measurement'
4
+ require 'yardstick/rake/verify'
5
+ require 'yaml'
6
+
7
+ options = YAML.load_file('config/yardstick.yml')
8
+
9
+ Yardstick::Rake::Measurement.new(:yardstick_measure, options) do |measurement|
10
+ measurement.output = 'measurement/report.txt'
11
+ end
12
+
13
+ Yardstick::Rake::Verify.new(:verify_measurements, options)
@@ -0,0 +1,55 @@
1
+ threshold: 100.0
2
+ require_exact_threshold: false
3
+ rules:
4
+ ApiTag::Presence:
5
+ enabled: true
6
+ exclude: []
7
+ ApiTag::Inclusion:
8
+ enabled: true
9
+ exclude: []
10
+ ApiTag::ProtectedMethod:
11
+ enabled: true
12
+ exclude: []
13
+ ApiTag::PrivateMethod:
14
+ enabled: true
15
+ exclude: []
16
+ ExampleTag:
17
+ enabled: true
18
+ exclude:
19
+ - Tarquinn.redirection_rule
20
+ - Tarquinn.skip_redirection
21
+ - Tarquinn.skip_redirection_rule
22
+ ReturnTag:
23
+ enabled: true
24
+ exclude:
25
+ - Tarquinn.redirection_rule
26
+ - Tarquinn.skip_redirection
27
+ - Tarquinn.skip_redirection_rule
28
+ - Tarquinn.redirector_builder
29
+ - Tarquinn#perform_redirection
30
+ - Tarquinn::RedirectionHandler#initialize
31
+ - Tarquinn::RequestHandler#initialize
32
+ - Tarquinn::RedirectionConfigBuilder#initialize
33
+ - Tarquinn::Condition::ProcRunner#initialize
34
+ - Tarquinn::Condition::MethodCaller#initialize
35
+ - Tarquinn::Condition::ActionChecker#initialize
36
+ - Tarquinn::Exception::RedirectionAlreadyDefined#initialize
37
+ Summary::Presence:
38
+ enabled: true
39
+ exclude:
40
+ - Tarquinn::RedirectionHandler#initialize
41
+ - Tarquinn::RequestHandler#initialize
42
+ - Tarquinn::RedirectionConfigBuilder#initialize
43
+ - Tarquinn::Condition::ProcRunner#initialize
44
+ - Tarquinn::Condition::MethodCaller#initialize
45
+ - Tarquinn::Condition::ActionChecker#initialize
46
+ - Tarquinn::Exception::RedirectionAlreadyDefined#initialize
47
+ Summary::Length:
48
+ enabled: true
49
+ exclude: []
50
+ Summary::Delimiter:
51
+ enabled: true
52
+ exclude: []
53
+ Summary::SingleLine:
54
+ enabled: true
55
+ exclude: []
data/docker-compose.yml CHANGED
@@ -17,7 +17,7 @@ services:
17
17
  depends_on: [base_build]
18
18
  command: /bin/bash -c 'rspec'
19
19
 
20
- test_all:
20
+ tarquinn_tests:
21
21
  <<: *base
22
22
  depends_on: [base_build]
23
23
  command: /bin/bash -c 'rspec && yard && rake yardstick_measure && rake verify_measurements'