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ó.