Add default #render_in implementation to ActiveModel::Conversion#57349
Conversation
Follow-up to [rails#46202][] Without overriding the new `#render_in` method, previous behavior will be preserved: render the view partial determined by calling `#to_partial_path`, then pass `object: self`. With the following view partial: ```erb <%# app/views/people/_person.html.erb %> <% local_assigns.with_defaults(shout: false) => { shout: } %> <%= shout ? person.name.upcase : person.name %> ``` Callers can render an instance of `Person` as a positional argument or a `:renderable` option: ```ruby person = Person.new(name: "Ralph") render person # => "Ralph" render person, shout: true # => "RALPH" render renderable: person # => "Ralph" render renderable: person, locals: { shout: true } # => "RALPH" ``` This preserves backward compatibility. At the same time, the `#render_in` method provides applications with an more flexibility, and an opportunity to manage how to transform models into Strings. For example, users of ViewComponent can map a model directly to a `ViewComponent::Base` instance. [rails#46202]: rails#46202 (comment)
|
@seanpdoyle Thanks for this PR! Unfortunately this broke my Rails app. I'm going to try to create a trimmed down version of the app to better identify the issue. I have a standard route/controller for an # app/controllers/api/bookings_controller.rb
class API::BookingsController < ApplicationController
def create
@booking = Booking.find params.expect(:id)
@booking.update update_params
response.status = :ok
end
endSince I'm not calling # app/views/api/bookings/update.json.jbuilder
json.partial! @bookingSince I'm not specifying which partial to render, Rails would automatically find this matching one: # app/views/api/bookings/_booking.json.jbuilder
json.extract! booking, :id, :statusThis last part is what's broken after this PR. Let me know if any of this rings a bell. Happy to share a more complete example if that's needed. |
|
@claudiob thank you for sharing that context. @guilleiguaran I've opened #57374 to revert this PR. I'll open a follow-up to incorporate tests that exercise the use-case outlined by @claudiob. |
…ersion`" This reverts commit 241f2a0. Based on a [comment][] on the original PR ([#57349][]), the `render` call does not incorporate controller-based view partial namespacing based on the render context. Since `ActiveModel::Conversion#render_in` is not yet released, this commit reverts the change in favor of a subsequent re-submission of the original PR to incorporate the newly documented edge case. [comment]: #57349 (comment)
Motivation / Background
Follow-up to #50623
Follow-up to #46202
The
#render_inmethod was introduced as an integration touch-point for views to intercept object rendering conventionally handled by Action View.This PR aims to provide Active Model-level (and therefore Active Record-level) flexibility to control how Action View transform models into HTML and JSON strings.
For example, users of the view_component gem can "intercept" model rendering to directly an instance to a
ViewComponent::Baseinstance.Detail
With the following view partial:
Callers can render an instance of
Personas a positional argument or a:renderableoption:This change aims to preserve backward compatibility by providing a default
#render_inmethod to relies on render the instance with a view partial inferred from combiningpartial: to_partial_pathandobject: self.Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]