Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.15.0 makes ViewComponent incompatible with use in an ActionMailer::Base subclass with a #format method #2177

Open
jrochkind opened this issue Dec 4, 2024 · 0 comments

Comments

@jrochkind
Copy link

This is a pretty niche conflict, but it took me a while to figure out, so figured I should report it at least for searchability for anyone else running into it.

As far as I can tell, #format is not a reserved method name in ActionMailer, or an existing method in ActionMailer. I have an ActionMailer that contains a #format method. It's .erb renders a ViewComponent.

This worked fine up to view_component 3.14.0, but started causing a problem exactly in view_component 3.15.0 (I determined through testing). Rails 7.2.2

The problem looks like:

ActionView::Template::Error:
       private method `format' called for an instance of OralHistoryRequest
     # /Users/jrochkind/.gem/ruby/3.3.4/gems/view_component-3.15.0/lib/view_component/base.rb:112:in `render_in'
     # ./app/views/oral_history_delivery_mailer/oral_history_delivery_email.html.erb:12:in `block in _app_views_oral_history_delivery_mailer_oral_history_delivery_email_html_erb___597500510261675183_408460'

Where the second line is just the line in my mailer ERB that tries to render a SomeViewComponent.new -- any at all will do.

The line mentioned at view_component-3.15.0/lib/view_component/base.rb:112 is pretty opaque to me, but... aha.

if compiler.renders_template_for?(@__vc_variant, request&.format&.to_sym)

This is observed in the process of running rspec-based tests, so it's possible it only appears as an artifact of testing harness, but does not look like it.

Changing the name of my mailer method #request to something else eliminates the problem.

OK, so it looks like then that line above in ViewComponent thinks that if the "container" for the ViewComponent (in this case a mailer) has a public #request method, then it's actually a controller (not a mailer), and the #request method is returning an ActionDispatch::Request which will have a public #format method it wants to use.

But in fact, it's in an ActionMailer, and that's my own #request method not rails, and it returns my own model object for my own use, and my own model object's #format is actually the (always in the way!) Kernel#format method which nobody wants or cares about and we always forget about, making this an even more confusing issue to debug!

This is a pretty edge case situation -- ViewComponent used in an ActionMailer that has it's own custom method named #request -- but it was surprising to run into a breakage on a minor version ViewComponent upgrade, and also fairly confusing to debug.

Perhaps it can be easily fixed though (don't assume public #format is a controller wtih an ActionDispatch::Request, check something else like class of receiver or returned object?) , or get better error message or docs or something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant