Renderring components automagically #522
Replies: 6 comments 3 replies
-
Yes, if you name your views consistently, you could definitely infer them from the controller/action. I wonder if defining a new method that delegates the arguments to the default view would be better than overloading def render_default(...)
view = Module.const_get("#{self.class.name.delete_suffix('Controller')}::#{action_name.classify}View")
render view.new(...)
end |
Beta Was this translation helpful? Give feedback.
-
I handle this implicit rendering with https://github.com/joelmoss/phlexible/#actioncontrollerimplicitrender It works really well with the responders gem too :) |
Beta Was this translation helpful? Give feedback.
-
@joeldrapper I like the view method as a shortcut! However I'm intrigued by @joelmoss 's option. @joelmoss could you give us an example of implicit rendering on a view with arguments that doesn't user responders? |
Beta Was this translation helpful? Give feedback.
-
This is pretty interesting related to the above https://github.com/rocketshipio/oxidizer |
Beta Was this translation helpful? Give feedback.
-
Here's my take (after flexing 💪 Phlex at https://fly.io/ruby-dispatch/component-driven-development-on-rails-with-phlex/):
|
Beta Was this translation helpful? Give feedback.
-
Building off the ideas here I added the following to my Rails project: # lib/phlex/rails/implicit_render.rb
module Phlex
module Rails
module ImplicitRender
def default_render
render_phlex_view({ action: action_name }) || super
end
def method_for_action(action_name)
super || ("default_phlex_render" if phlex_view(action_name))
end
def default_phlex_render
render phlex_view(action_name)
end
def render_phlex_view(options)
options[:action] ||= action_name
return unless (view = phlex_view(options[:action]))
render view, options
end
private
def phlex_view(action_name = @_action_name)
assign_ivars phlex_view_path(action_name).camelize.safe_constantize.new
end
def phlex_view_path(action_name)
"#{controller_path}/#{action_name}_view"
end
def assign_ivars(phlex_view)
phlex_view.tap do |view|
view_assigns.each do |variable, value|
attr_writer_name = "#{variable}="
view.send attr_writer_name, value if view.respond_to?(attr_writer_name)
warn "[#{phlex_view.class.name}] Unprocessed ivar (@#{variable}). To correct add `attr_writer :#{variable}` or `def #{variable}=(value)` to this Phlex View" if ::Rails.env.development? && !view.respond_to?(attr_writer_name)
end
end
end
end
end
end I then updated my class ApplicationController < ActionController::Base
include Phlex::Rails::ImplicitRender
layout -> { ApplicationLayout }
allow_browser versions: :modern
end Example Controller # app/controllers/dashboards_controller.rb
class DashboardsController < ApplicationController
def show
@greeting = "Hiya"
@unknown = 42
@another_one = "Khaled"
end
end Example Phlex View # app/views/dashboards/show_view.rb
class Dashboards::ShowView < ApplicationView
attr_writer :greeting
def view_template
h1 { "Dashboards::ShowView" }
p { "#{@greeting}, User!" }
end
end The dev log warns of the ivars defined but unused because the view lacks the ability to accept them:
|
Beta Was this translation helpful? Give feedback.
-
Hey @joeldrapper!
I've been thinking of a developer experience addition for phlex-rails (and possibly ViewComponent) that would make it feel a bit closer to what you do in regular Rails.
I personally love that templates are rendered without me having to think about it. Yes, globally available instance variables can come and bite you but the general idea... the general feeling of it being automagical is just amazing.
Do you think we could achieve something similar with class based views?
I imagine something like:
The call to
render locals: { ... }
could go through a process of inference where it looks for every possibility: template, phlox-view, view-component etc.Rails probably already does something similar when inferring the template extension based on the request format.
What do you think?
Beta Was this translation helpful? Give feedback.
All reactions