37 votos

Rieles, Cómo se representa una vista/parcial en un modelo de

En mi modelo tengo:

after_create :push_create

Yo push_create necesito representar una vista. Estoy tratando de hacer que así:

  def push_event(event_type)
    X["XXXXX-#{Rails.env}"].trigger(event_type, 
      {
        :content => render( :partial =>"feeds/feed_item", :locals => { :feed_item => self })
      }
    )
  end

Este angers rieles, ya que no me gusta de representación de una vista en el modelo, pero me necesitan allí.

Error:

NoMethodError (undefined method `render' for #<WallFeed:0x1039be070>):

Sugerencias? Debo hacerla en algún otro lugar de alguna manera? O ¿cómo puedo representar en el modelo para establecer el contenido? Gracias

56voto

stephan.com Puntos 756

solución adecuada

Así, "ellos" están a la derecha. Usted realmente tiene que hacer la representación en un controlador: pero es un juego justo para llamar a ese controlador a partir de una modelo! Afortunadamente, AbstractController en Rails 3 hace que sea más fácil de lo que pensaba. Terminé de hacer una simple ActionPusher clase, trabajando como ActionMailer. Tal vez voy a conseguir ambicioso y hacer de esto una adecuada joya algún día, pero esto debe servir como un buen punto de inicio para cualquier otra persona en mis zapatos.

Tengo la mayoría de la 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/pulsadores/users_pusher.rb. Supongo que la requieren 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, solo puedo hacer esto:

after_commit :push_add_notice

private

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

y, a continuación, usted 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 usted realmente no necesita hacerlo con Pushable interior de la clase y de la .empuje llame a la final, pero yo quería hacer que se vea como ActiveMailer. También tengo un pusher_key método en mi modelo de usuario, para hacer un canal para cada usuario pero, en este es mi primer día con cualquier cosa como Empujador, así que no puedo decir con certeza si esa es la forma correcta de la estrategia. Hay más para ser estudiados, pero esto es suficiente para mí para empezar.

Buena suerte!

(este fue mi primer proyecto de respuesta, dejando en él porque podría ayudar a alguien)

Tengo el esquema general de una solución de trabajo. Como este, en el 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

que es sin duda el trabajo - la plantilla es la representación, y se eval()'ed en el lado del cliente con éxito. Creo que lo voy a limpiar, casi seguro que mover render_anywhere en algún lugar más generales, y probablemente se trate de algo como esto

Puedo ver que empuja tendrá sus propias plantillas, llamando a la generalmente los disponibles, y yo podría tratar de recoger a todos en un solo lugar. Un bonito y pequeño problema es que yo a veces uso controller_name en mi parciales, como a la luz de un elemento de menú, pero obviamente voy a tener que tomar una táctica diferente allí. Supongo que voy a tener que hacer algo para conseguir más ayudantes disponibles, pero no he llegado ahí todavía.

El éxito! ¡Hurra! Esto debe responder a su pregunta, y la mía -, voy a añadir más detalle si le parece oportuno, más adelante. Buena suerte!!!!

original de la no-respuesta de hace una hora a la izquierda para mayor claridad

No tengo una respuesta, pero esta pregunta oportuna merece más la aclaración, y tengo la esperanza de conseguir más cerca de mi respuesta, ayudando a preguntar :)

Estoy frente al mismo problema. Para explicar un poco más claramente, Empujador de forma asincrónica envía el contenido a un usuario conectado navegador. Un caso de uso típico sería una muestra de que el usuario tiene un nuevo mensaje de otro usuario. Con Empujador, usted puede pulsar un mensaje para el receptor del navegador, por lo que obtener una notificación inmediata si se registran. Una gran demostración de lo que Empujador puede hacer, echa un vistazo http://wordsquared.com/

Usted puede enviar cualquier tipo de datos que desee, como un JSON hash interpretar como quiera, pero sería muy conveniente enviar RJS, al igual que con cualquier otra llamada ajax y eval() en el lado del cliente. De esa manera, usted puede (por ejemplo) hacer la plantilla para su barra de menú, la actualización de la misma en su totalidad, o sólo en el nuevo número de mensaje que se muestra al usuario, usando todos el mismo parciales para mantener SECAS. En principio, usted puede hacer que el parcial del remitente del controlador, pero que no tiene mucho sentido, y no podría ser incluso una solicitud, que puede ser desencadenada por un cron job, por ejemplo, o algún otro evento, como el precio de una acción de cambio. El remitente controlador simplemente no tienen que saberlo - me gusta mantener mi controladores en una dieta de hambre ;)

Esto podría sonar como una violación de MVC, pero realmente no es - y lo que realmente debe ser resuelto con algo como ActionMailer, sino de compartir los ayudantes y los parciales con el resto de la aplicación. Sé que en mi aplicación, me gustaría enviar un Empujador evento en el mismo momento (o en lugar de) una de ActionMailer llamada. Quiero dar una arbitraria parcial para el usuario B basado en un evento de usuario A.

Estos enlaces pueden señalar el camino hacia una solución:

El último parece más prometedor, ofreciendo esta tentadora fragmento de código:

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

Como hace este enlace proporcionado por otro cartel de arriba.

Voy a informar si puedo conseguir algo de trabajo

tl;dr: yo también!

41voto

Kevin Puntos 1618

Tal vez es más fácil de lo que solía ser, pero acabo de hacer esto:

ApplicationController.new.render_to_string(:partial => 'messages/any', :object => im)

Render_to_string necesita para ser llamado desde un controlador, así que crear una instancia de una nueva copia del controlador genérico.

15voto

hsgubert Puntos 1031

Usted puede utilizar ActionView directamente y de rendir los parciales a la cadena sin necesidad de un controlador. Me parece que el patrón útil para crear modelos que sintetizan algunos de javascript generación, por ejemplo.

html = ActionView::Base.new(Rails.configuration.paths['app/views']).render(
  :partial => 'test', 
  :formats => :html,
  :handlers => :erb,
  :locals => { :fake_variable => 'fake_value' }
)

Luego, sólo hay que poner su _test.html.erb en ver carpeta y probarlo!

2voto

Peter P. Puntos 973

la "correcta" forma de hacer esto es para empujar un objeto en forma serializada(json) y, a continuación, tienen la opinión de tratar con él de una vez que el evento es recibido. Quizás desee usar el Manillar para representar el objeto.

Edit: originalmente escribí acerca de cómo, a pesar de mi respuesta, yo iba a seguir su ejemplo. Pero me acabo de dar cuenta de que hay una ENORME gotcha con su enfoque cuando se trata de las notificaciones push.

En su problema, usted está haciendo las notificaciones push a un usuario. Para mí, yo era la radiodifusión a un conjunto de usuarios. Así que iba a representar html con una presunción de "current_user" y todo lo que viene con ella(por ejemplo, la lógica, permisos, etc). Esto NO es BUENO ya que cada notificación de inserción serán recibidos por un "usuario actual".

Por lo tanto, realmente, sólo necesita enviar de nuevo los datos, y dejar que cada punto de vista individual de manejar.

2voto

marflar Puntos 13293

Estoy bastante seguro de que las respuestas que usted busca se encuentran dentro de la Elaboración de Aplicaciones Rails, donde José Valim entra en gran detalle acerca de cómo y por qué usted desea procesar vistas directamente desde tu db

Siento no poder ser de más ayuda pero ya que he empezado a leer yo mismo esta noche.

Usted puede encontrar un poco de ayuda aquí - es una entrada de blog acerca de hacer este tipo de cosas, aunque con métodos diferentes a la tuya

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X