Repository: ViewComponent/view_component (Ruby)

Issue:
Can not use "request" as argument 
### Steps to reproduce
Having `request` as a argument to a component fails, eg
```ruby
class ExampleComponent < ViewComponent::Base
  def initialize(request:)
    @request = request
  end
end
```
Running `render(ExampleComponent.new(request: "My Title"))` 
will result in:
```
private method `format' called for an instance of String
```

A repo with the error is at https://github.com/erikaxel/view_component-request-bug-replica

### System configuration
Using `request` worked before version 3.15, my assumption is that https://github.com/ViewComponent/view_component/pull/2079 is the culprit. 


Discussion: @erikaxel Thanks for opening this! Can you share a full backtrace?
Yeah, sorry for not including it in the original bug report. Here is the one from the demo repo:
```
[view_component (3.15.1) lib/view_component/base.rb:112:in `render_in'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/template/renderable.rb:16:in `render'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/template_renderer.rb:66:in `block (2 levels) in render_template'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications.rb:210:in `block in instrument'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications/instrumenter.rb:58:in `instrument'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications.rb:210:in `instrument'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/template_renderer.rb:60:in `block in render_template'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/template_renderer.rb:76:in `block in render_with_layout'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications.rb:210:in `block in instrument'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications/instrumenter.rb:58:in `instrument'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications.rb:210:in `instrument'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/template_renderer.rb:75:in `render_with_layout'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/template_renderer.rb:59:in `render_template'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/template_renderer.rb:11:in `render'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/renderer.rb:58:in `render_template_to_object'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/renderer/renderer.rb:31:in `render_to_object'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/rendering.rb:135:in `block in _render_template'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/base.rb:308:in `in_rendering_context'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/rendering.rb:134:in `_render_template'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/streaming.rb:258:in `_render_template'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/rendering.rb:121:in `render_to_body'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/rendering.rb:186:in `render_to_body'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/renderers.rb:142:in `render_to_body'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/abstract_controller/rendering.rb:29:in `render'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/rendering.rb:167:in `render'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:32:in `block (2 levels) in render'](http://127.0.0.1:3000/#)
[/Users/erikaxel/.asdf/installs/ruby/3.3.4/lib/ruby/3.3.0/benchmark.rb:313:in `realtime'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/core_ext/benchmark.rb:14:in `ms'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:32:in `block in render'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:101:in `cleanup_view_runtime'](http://127.0.0.1:3000/#)
[activerecord (7.2.1) lib/active_record/railties/controller_runtime.rb:46:in `cleanup_view_runtime'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:31:in `render'](http://127.0.0.1:3000/#)
[app/controllers/home_controller.rb:3:in `index'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/basic_implicit_render.rb:8:in `send_action'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/abstract_controller/base.rb:226:in `process_action'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/rendering.rb:193:in `process_action'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/abstract_controller/callbacks.rb:261:in `block in process_action'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/callbacks.rb:110:in `run_callbacks'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/abstract_controller/callbacks.rb:260:in `process_action'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/rescue.rb:27:in `process_action'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:77:in `block in process_action'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications.rb:210:in `block in instrument'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications/instrumenter.rb:58:in `instrument'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/notifications.rb:210:in `instrument'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:76:in `process_action'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal/params_wrapper.rb:259:in `process_action'](http://127.0.0.1:3000/#)
[activerecord (7.2.1) lib/active_record/railties/controller_runtime.rb:39:in `process_action'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/abstract_controller/base.rb:163:in `process'](http://127.0.0.1:3000/#)
[actionview (7.2.1) lib/action_view/rendering.rb:40:in `process'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal.rb:252:in `dispatch'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_controller/metal.rb:335:in `dispatch'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/routing/route_set.rb:67:in `dispatch'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/routing/route_set.rb:50:in `serve'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/journey/router.rb:53:in `block in serve'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/journey/router.rb:133:in `block in find_routes'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/journey/router.rb:126:in `each'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/journey/router.rb:126:in `find_routes'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/journey/router.rb:34:in `serve'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/routing/route_set.rb:896:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/static.rb:27:in `call'](http://127.0.0.1:3000/#)
[rack (3.1.7) lib/rack/tempfile_reaper.rb:20:in `call'](http://127.0.0.1:3000/#)
[rack (3.1.7) lib/rack/etag.rb:29:in `call'](http://127.0.0.1:3000/#)
[rack (3.1.7) lib/rack/conditional_get.rb:31:in `call'](http://127.0.0.1:3000/#)
[rack (3.1.7) lib/rack/head.rb:15:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/http/permissions_policy.rb:38:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/http/content_security_policy.rb:36:in `call'](http://127.0.0.1:3000/#)
[rack-session (2.0.0) lib/rack/session/abstract/id.rb:272:in `context'](http://127.0.0.1:3000/#)
[rack-session (2.0.0) lib/rack/session/abstract/id.rb:266:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/cookies.rb:704:in `call'](http://127.0.0.1:3000/#)
[activerecord (7.2.1) lib/active_record/migration.rb:674:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/callbacks.rb:31:in `block in call'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/callbacks.rb:101:in `run_callbacks'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/callbacks.rb:30:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/executor.rb:16:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/actionable_exceptions.rb:18:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:31:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/show_exceptions.rb:32:in `call'](http://127.0.0.1:3000/#)
[railties (7.2.1) lib/rails/rack/logger.rb:41:in `call_app'](http://127.0.0.1:3000/#)
[railties (7.2.1) lib/rails/rack/logger.rb:29:in `call'](http://127.0.0.1:3000/#)
[sprockets-rails (3.5.2) lib/sprockets/rails/quiet_assets.rb:17:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/remote_ip.rb:96:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/request_id.rb:33:in `call'](http://127.0.0.1:3000/#)
[rack (3.1.7) lib/rack/method_override.rb:28:in `call'](http://127.0.0.1:3000/#)
[rack (3.1.7) lib/rack/runtime.rb:24:in `call'](http://127.0.0.1:3000/#)
[activesupport (7.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/server_timing.rb:61:in `block in call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/server_timing.rb:26:in `collect_events'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/server_timing.rb:60:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/executor.rb:16:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/static.rb:27:in `call'](http://127.0.0.1:3000/#)
[rack (3.1.7) lib/rack/sendfile.rb:114:in `call'](http://127.0.0.1:3000/#)
[actionpack (7.2.1) lib/action_dispatch/middleware/host_authorization.rb:143:in `call'](http://127.0.0.1:3000/#)
[railties (7.2.1) lib/rails/engine.rb:535:in `call'](http://127.0.0.1:3000/#)
[puma (6.4.3) lib/puma/configuration.rb:272:in `call'](http://127.0.0.1:3000/#)
[puma (6.4.3) lib/puma/request.rb:100:in `block in handle_request'](http://127.0.0.1:3000/#)
[puma (6.4.3) lib/puma/thread_pool.rb:378:in `with_force_shutdown'](http://127.0.0.1:3000/#)
[puma (6.4.3) lib/puma/request.rb:99:in `handle_request'](http://127.0.0.1:3000/#)
[puma (6.4.3) lib/puma/server.rb:464:in `process_client'](http://127.0.0.1:3000/#)
[puma (6.4.3) lib/puma/server.rb:245:in `block in run'](http://127.0.0.1:3000/#)
[puma (6.4.3) lib/puma/thread_pool.rb:155:in `block in spawn_thread'](http://127.0.0.1:3000/#)
```



Fix (patch):
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 070f16524..2e3ff1d6b 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,10 @@ nav_order: 5
 
 ## main
 
+* Enable components to use `@request` and `request` methods/ivars.
+
+    *Blake Williams*
+
 * Fix bug where implicit locales in component filenames threw a `NameError`.
 
     *Chloe Fons*
diff --git a/lib/view_component/base.rb b/lib/view_component/base.rb
index 9e6ddb701..8d9ecde03 100644
--- a/lib/view_component/base.rb
+++ b/lib/view_component/base.rb
@@ -109,10 +109,10 @@ def render_in(view_context, &block)
 
       if render?
         rendered_template =
-          if compiler.renders_template_for?(@__vc_variant, request&.format&.to_sym)
-            render_template_for(@__vc_variant, request&.format&.to_sym)
+          if compiler.renders_template_for?(@__vc_variant, __vc_request&.format&.to_sym)
+            render_template_for(@__vc_variant, __vc_request&.format&.to_sym)
           else
-            maybe_escape_html(render_template_for(@__vc_variant, request&.format&.to_sym)) do
+            maybe_escape_html(render_template_for(@__vc_variant, __vc_request&.format&.to_sym)) do
               Kernel.warn("WARNING: The #{self.class} component rendered HTML-unsafe output. The output will be automatically escaped, but you may want to investigate.")
             end
           end.to_s
@@ -286,7 +286,14 @@ def format
     #
     # @return [ActionDispatch::Request]
     def request
-      @request ||= controller.request if controller.respond_to?(:request)
+      __vc_request
+    end
+
+    # Enables consumers to override request/@request
+    #
+    # @private
+    def __vc_request
+      @__vc_request ||= controller.request if controller.respond_to?(:request)
     end
 
     # The content passed to the component instance as a block.
@@ -328,7 +335,7 @@ def content_evaluated?
     end
 
     def maybe_escape_html(text)
-      return text if request && !request.format.html?
+      return text if __vc_request && !__vc_request.format.html?
       return text if text.blank?
 
       if text.html_safe?