Saltar al contenido

Rails, Cómo renderizar una vista / parcial en un modelo

Haz todo lo posible por entender el código correctamente antes de adaptarlo a tu trabajo si tquieres aportar algo puedes dejarlo en la sección de comentarios.

Solución:

solución adecuada

Bueno, “ellos” tienen razón. Realmente tienes que hacer el renderizado en un controlador, ¡pero es un juego justo llamar a ese controlador desde un modelo! Afortunadamente, AbstractController en Rails 3 lo hace más fácil de lo que pensaba. Terminé haciendo una clase ActionPusher simple, funcionando como ActionMailer. Quizás sea ambicioso y haga de esta una verdadera joya algún día, pero esto debería servir como un buen comienzo para cualquier otra persona en mi lugar.

Obtuve la mayor ayuda de este enlace: http://www.amberbit.com/blog/2011/12/27/render-views-and-partials-outside-controllers-in-rails-3/

en lib / action_pusher.rb

class ActionPusher < AbstractController::Base
  include AbstractController::Rendering
  include AbstractController::Helpers
  include AbstractController::Translation
  include AbstractController::AssetPaths
  include Rails.application.routes.url_helpers
  helper ApplicationHelper
  self.view_paths = "app/views"

  class Pushable
    def initialize(channel, pushtext)
      @channel = channel
      @pushtext = pushtext
    end

    def push
      Pusher[@channel].trigger('rjs_push', @pushtext )
    end
  end
end

en app / pushers / users_pusher.rb. Supongo que el requerimiento podría ir a algún lugar más global.

require 'action_pusher'

class UsersPusher < ActionPusher
  def initialize(user)
    @user = user
  end

  def channel
    @user.pusher_key
  end

  def add_notice(notice = nil)
    @notice = notice
    Pushable.new channel, render(template: 'users_pusher/add_notice')
  end
end

Ahora en mi modelo, puedo hacer esto:

after_commit :push_add_notice

private

def push_add_notice
  UsersPusher.new(user).add_notice(self).push
end

y luego querrá un parcial, por ejemplo, app / views / users_pusher / add_notice.js.haml, que podría ser tan simple como:

alert('#@notice.body')

Supongo que realmente no necesitas hacerlo con la clase interna Pushable y la llamada .push al final, pero quería que se pareciera a ActiveMailer. También tengo un método pusher_key en mi modelo de usuario, para hacer un canal para cada usuario, pero este es mi primer día con algo como Pusher, así que no puedo decir con certeza si esa es la estrategia correcta. Hay más para desarrollar, pero esto es suficiente para comenzar.

¡Buena suerte!

(este fue mi primer borrador de respuesta, lo dejé porque podría ayudar a alguien)

Tengo el esquema general de una solución que funciona. Así, en tu modelo:

after_create :push_new_message

private

def render_anywhere(partial, assigns = )
  view = ActionView::Base.new(ActionController::Base.view_paths, assigns)
  view.extend ApplicationHelper
  view.render(:partial => partial)
end  

def push_new_message
  pushstring = render_anywhere('notices/push_new_message', :message_text => self.body)
  Pusher[user.pusher_key].trigger!('new_message', pushstring)
end

eso definitivamente está funcionando: la plantilla se está procesando y obtiene eval () 'ed en el lado del cliente con éxito. Estoy planeando limpiarlo, es casi seguro mover render_anywhere a algún lugar más general, y probablemente probar algo como esto

Puedo ver que los empujes necesitarán sus propias plantillas, llamando a las disponibles generalmente, y puedo intentar recopilarlas todas en un solo lugar. Un pequeño problema agradable es que a veces uso controller_name en mis parciales, me gusta iluminar un elemento del menú, pero obviamente tendré que tomar una táctica diferente allí. Supongo que podría tener que hacer algo para tener más ayudantes disponibles, pero todavía no he llegado allí.

¡Éxito! ¡Hurra! Esto debería responder a su pregunta y a la mía; agregaré más detalles si me parece apropiado más adelante. ¡¡¡¡Buena suerte!!!!

La falta de respuesta original de hace una hora se fue para mayor claridad.

No tengo una respuesta, pero esta oportuna pregunta merece más aclaración, y espero acercarme a mi responde ayudando a preguntar 🙂

Estoy enfrentando el mismo problema. Para explicarlo un poco más claramente, Pusher envía contenido de forma asíncrona a un navegador de usuario conectado. Un caso de uso típico sería mostrarle al usuario que tiene un nuevo mensaje de otro usuario. Con Pusher, puede enviar un mensaje al navegador del receptor, para que reciba una notificación inmediata si está conectado. Para obtener una demostración realmente excelente de lo que puede hacer Pusher, visite http://wordsquared.com/

Puede enviar cualquier dato que desee, como un hash JSON para interpretar cómo le gusta, pero sería muy conveniente enviar RJS, al igual que con cualquier otra llamada ajax y evaluarlo () en el lado del cliente. De esa manera, podría (por ejemplo) renderizar la plantilla para su barra de menú, actualizándola en su totalidad, o simplemente el nuevo recuento de mensajes que se muestra al usuario, usando los mismos parciales para mantenerlo SECO. En principio, podría renderizar el parcial de la del remitente controlador, pero eso tampoco tiene mucho sentido, y puede que ni siquiera haya una solicitud, podría desencadenarse por un trabajo cron, por ejemplo, o algún otro evento, como un cambio en el precio de las acciones. El controlador del remitente simplemente no debería tener que saberlo; me gusta mantener mis controladores en una dieta de hambre;)

Puede parecer una violación de MVC, pero en realidad no lo es, y realmente debería resolverse con algo como ActionMailer, pero compartiendo ayudantes y parciales con el resto de la aplicación. Sé que en mi aplicación, me gustaría enviar un evento Pusher al mismo tiempo (o en lugar de) una llamada a ActionMailer. Quiero representar un parcial arbitrario para el usuario B basado en un evento del usuario A.

Estos enlaces pueden indicar el camino hacia una solución:

  • http://blog.choonkeat.com/weblog/2006/08/rails-calling-r.html
  • Cómo renderizar un parcial a partir de un modelo en Rails 2.3.5
  • http://mattwindsurfs.wordpress.com/2008/06/19/rails-render-in-a-model/
  • http://davetroy.blogspot.com/2008/02/actsasrenderer-brings-output-to-models.html
  • https://github.com/asapnet/acts_as_renderer
  • http://ethilien.net/archives/render-rails-templates-anywhere-even-in-a-model/

El último parece el más prometedor y ofrece este tentador fragmento:

def render_anywhere(partial, assigns)
  view = ActionView::Base.new(Rails::Configuration.new.view_path, assigns)
  ActionView::Base.helper_modules.each  
  view.extend ApplicationHelper
  view.render(:partial => partial)
end

Al igual que este enlace proporcionado por otro cartel anterior.

Informaré si consigo que algo funcione

tl; dr: ¡yo también!

Yo solo hago esto:

ApplicationController.new.render_to_string(partial: 'messages/any', locals:  variable: 'value' )

Rieles de 5 vías

En rieles 5 renderizado fuera de un controlador se volvió bastante sencillo debido a la implementación render método de clase de controlador:

# render template
ApplicationController.render 'templates/name'
# render action
FooController.render :index
# render file
ApplicationController.render file: 'path'
# render inline
ApplicationController.render inline: 'erb content'

Al llamar render fuera de un controlador, se pueden asignar variables de instancia a través de assigns opción y use cualquier otra opción disponible desde dentro de un controlador:

ApplicationController.render(
  assigns:  article: Article.take ,
  template: 'articles/show',
  layout: false
)

Solicitar entorno se puede personalizar a través de las opciones predeterminadas

ApplicationController.render inline: '<%= users_url %>'
# => 'http://default_host.com/users'

ApplicationController.renderer.defaults[:http_host] = 'custom_host.org'
# => "custom_host.org"

ApplicationController.render inline: '<%= users_url %>'
# => 'http://custom_host.org/users'

o explícitamente inicializando un nuevo renderizador

renderer = ApplicationController.renderer.new(
  http_host: 'custom_host.org',
  https: true
)
renderer.render inline: '<%= users_url %>'
# => 'https://custom_host.org/users'

Espero que ayude.

Aquí puedes ver las comentarios y valoraciones de los usuarios

Tienes la posibilidad comunicar este post si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *