ruby-on-rails - software - ruby on rails tutorial
Forma recomendada de usar los ayudantes de vista de Rails en una clase de presentaciĆ³n (2)
He estado investigando la forma ''recomendada'' de utilizar los ayudantes de vista de Rails (por ejemplo, link_to
, content_tag
) en una clase simple de ruby, como un presentador. Parece que hay muy poca información en este frente y quería tener una idea de lo que pensaba la comunidad de Stack.
Entonces, las opciones que tenemos son ... (nota, estoy usando Rails 4, y estoy menos preocupado por las versiones anteriores)
Incluya los módulos requeridos manualmente
Esta es probablemente la forma más limpia, ya que solo se incluyen los ayudantes necesarios. Sin embargo, he encontrado que este método no funciona en algunos casos, ya que el contexto de vista habitual proporcionado en los ayudantes simples de Rails está configurado para la solicitud actual. url_for
no sabría sobre la solicitud actual, por ejemplo, por lo que es posible que el host no coincida.
class MyPresenter
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::CaptureHelper
def wrapped_link
content_tag :div, link_to(''My link'', root_url)
end
end
Use ActionController::Base.helpers
Desde Rails 3, ActionController::Base
ha incluido un método de helpers
para acceder al contexto de vista actual. Creo que el contexto de visualización proporcionado por este método está configurado como en un raíl auxiliar, pero podría estar equivocado. No hay realmente ninguna documentación sobre esto que parezca preocupante, pero funciona bastante bien en la práctica.
class MyPresenter
def wrapped_link
h.content_tag :div, h.link_to(''My link'', h.root_url)
end
protected
def h
ActionController::Base.helpers
end
end
Creo que este contexto de vista también se puede combinar con include
, pero los ayudantes de vista de rieles tienen cientos de métodos y se siente sucio incluirlos indiscriminadamente.
Inyectar el contexto de la vista al llamar al presentador
Finalmente, podríamos pasar el contexto de vista a la clase cuando se inicializa (o alternativamente en un método de render
)
class MyPresenter
attr_accessor :context
alias_method :h, :context
def initialize(context)
@context = context
end
def wrapped_link
h.content_tag :div, h.link_to(''My link'', h.root_url)
end
end
class MyController < ApplicationController
def show
# WARNING - `view_context` in a controller creates an object
@presenter = MyPresenter.new(view_context)
end
end
Personalmente tiendo a inclinarme hacia las últimas dos opciones, pero sin una respuesta definitiva del equipo de Rails (que he podido encontrar) me sentí un poco inseguro. ¿Quién mejor para preguntar que Stack?
Me gustaría ir con la mezcla de la segunda y tercera opción, algo así como:
class MyPresenter
def initialize(helpers)
@h = helpers
end
def wrapped_link
h.content_tag :div, h.link_to(''My link'', h.root_url)
end
private
attr_reader :h
end
Su segunda opción requiere que todas las pruebas de su unidad se califiquen como ActionController::Base.helpers
que tal vez no sea una buena opción, y su tercera opción está usando un contexto enorme para acceder solo a algunos métodos.
Realmente lo haría dependiente de qué tipo de métodos usas. Si se trata solo de lo básico como content_tag
etc. Me ActionController::Base.helpers
método ActionController::Base.helpers
. También es posible llamar directamente a algunos ayudantes, por ejemplo, para las rutas dentro de los modelos, casi siempre uso algo a lo largo de las líneas de Rails.application.routes.url_helpers.comment_path
.
Para cosas específicas del controlador, la tercera opción puede ser útil, pero personalmente la forma "pura" parece más agradable. Draper también tiene un enfoque interesante: guardan el view_context
para la solicitud actual y luego delegan las llamadas a h
-helpers a él: https://github.com/drapergem/draper/blob/master/lib/draper/view_context.rb
Realmente es solo una cuestión de preferencia. Nunca incluiría a todos los ayudantes a la vez, como ya dijiste. Pero la segunda opción es bastante buena si quiere construir la capa de presentación usted mismo sin usar una gema como Draper o Cells.