Rails, Hoe de weergave van een view/gedeeltelijk in een model

In mijn model heb ik:

after_create :push_create

Ik push_create ik moet met de weergave van een beeld. Ik probeer dat zo:

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

Dit angers rails, als het niet net als ik de weergave van een beeld in het model, maar ik moet het er.

Fout:

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

Suggesties? Moet ik dat het ergens anders een of andere manier? Of hoe kan ik de render in het model om de inhoud? Dankzij

  • dit is een fundamenteel verkeerde benadering. Waarom niet na de filter in de controller ?
  • Ik ben met behulp van drukknop app, zo gaat dat in het model.
  • ik weet niet echt wat drukker is, maar ik zie niet in hoe een echt slechte programmering praktijk betrekking heeft op een toepassing om het te maken moet gebruiken. Filters en rendering moet altijd behandeld worden door een controller.
  • Bedankt dus hoe kan ik weer de controller van de binnenkant van het model voor het opslaan van het resultaat in een veld?
  • Kunt u gebruik maken van een helper in een model?
  • u kunt gebruik maken van een helper waar u wilt, zo ver als ik weet, maar de weergave methoden die zijn gedefinieerd op de controller, dus een helper niet echt koop je niets.
  • Wat in dat ‘feeds/feed_item’ gedeeltelijke? Wat probeert u te verzenden in dat :content param?
  • Voor iedereen die van Google op zoek naar de Rails 5 manier om dit te doen, @olegafanasyev heeft het een ingebouwde weg te gaan, een beetje verderop in de weg.

 

10 Replies
  1. 65

    juiste oplossing

    Goed, “ze” hebben gelijk. Wat je echt moet doen is de rendering in een controller –
    maar het is eerlijk spel te bellen controller van een model! Gelukkig AbstractController
    in Rails 3 maakt het makkelijker dan ik dacht. Ik wond tot het maken van een eenvoudig
    ActionPusher klasse, werkt net als ActionMailer. Misschien dat ik voor ambitieuze en
    is dit een juiste gem dag, maar dit moet dienen als een goede start voor iemand anders in mijn schoenen.

    Ik heb de meeste hulp van deze link: http://www.amberbit.com/blog/2011/12/27/render-views-and-partials-outside-controllers-in-rails-3/

    in 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

    in app/duwboten/users_pusher.rb. Ik denk dat het nodig zou kunnen gaan ergens meer wereldwijd?

    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

    Nu in mijn model, kan ik gewoon dit doen:

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

    en dan zult u wilt een gedeeltelijke, bijv. app/views/users_pusher/add_notice.js.haml, die kan zo simpel zijn als:

    alert('#{@notice.body}')

    Ik denk dat je niet echt nodig hebt om het te doen met Pushable innerlijke klasse .druk
    oproep aan het eind, maar ik wilde het eruit ActiveMailer. Ik heb ook een
    pusher_key methode op mijn gebruiker een model, om een kanaal voor elke gebruiker, maar dit
    mijn eerste dag met iets als Pusher, dus ik kan niet met zekerheid zeggen als dat de juiste
    strategie. Er is meer te worden uitgewerkt, maar dit is genoeg voor mij aan de slag te gaan.

    Goed geluk!

    (dit was mijn eerste ontwerp van antwoord, waarbij het in omdat het kan helpen om iemand)

    Ik heb de algemene schets van een oplossing werken. Als dit in uw model:

    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

    dat is zeker werken – het sjabloon is te renderen en krijgt eval()’ed op de client met succes. Ik ben van plan om het op te ruimen, bijna zeker verplaatsen render_anywhere ergens meer algemeen, en waarschijnlijk proberen iets als dit

    Ik kan zien dat duwt zal moeten eigen templates, het aanroepen van de over het algemeen beschikbaar zijn, en ik kan proberen om ze alle te verzamelen op één plaats. Een klein probleem is dat ik soms gebruik controller_name in mijn partiële protheses, zoals aan het licht van een menu-item, maar ik zal het uiteraard ook op een andere tactiek er. Ik gok dat ik misschien iets doen om meer helpers beschikbaar, maar ik heb niet gekregen er nog niet.

    Succes! Hoera! Dit moet antwoord geven op je vraag, en de mijne – ik voeg meer detail als dat nodig lijkt later. Goed geluk!!!!

    originele niet-beantwoorden van een uur geleden vertrokken voor de duidelijkheid

    Ik geen antwoord heb, maar dit tijdig vraag verdient meer duidelijkheid, en ik hoop dat ik dichter bij mijn antwoord door te helpen vragen 🙂

    Ik ben geconfronteerd met hetzelfde probleem. Om uit te leggen een beetje meer duidelijk, Pusher asynchroon stuurt de inhoud van een aangesloten gebruiker browser. Een typische use case zou een met de gebruiker hebben ze een nieuw bericht van een andere gebruiker. Met Drukknop, kunt u een push bericht naar de ontvanger van de browser, dus krijgen ze een direct bericht als ze zijn ingelogd. Voor een echt geweldige demo van wat Duwboot kan doen, check out http://wordsquared.com/

    U kunt het verzenden van alle gegevens die u wilt, zoals een JSON-hash te interpreteren hoe je het wilt, maar het zou heel handig te verzenden RJS, net zoals met een ajax call eval() op de client-side. Op die manier kon je (bijvoorbeeld) maken het sjabloon voor uw menu, bijwerken in zijn geheel, of gewoon een nieuw bericht te rekenen aan de gebruiker, met alle voor dezelfde partiële protheses te houden is het kurkdroog. In principe kan ertoe leiden dat de prothese uit de afzender controller, maar dat maakt niet veel zin te maken, en er misschien niet eens een verzoek zouden kunnen worden veroorzaakt door een cron job, bijvoorbeeld, of een andere gebeurtenis, zoals een koers veranderen. De afzender controller gewoon moeten niet weet, hou ik mijn controllers op een honger dieet 😉

    Het klinkt misschien als een schending van de MVC, maar het is echt niet – en het moet echt opgelost worden met iets als ActionMailer, maar het delen van helpers en boventonen met de rest van de app. Ik weet in mijn app, ik wil graag een Duwboot gebeurtenis op hetzelfde moment als (of in plaats van) een ActionMailer noemen. Ik wil het genereren van een willekeurige gedeeltelijk voor gebruiker B op basis van een gebeurtenis van gebruiker A.

    Deze links kunnen de weg wijzen in de richting van een oplossing:

    De laatste lijkt de meest veelbelovende, het aanbieden van dit prikkelende fragment:

    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

    Als deze link geleverd door een andere poster hierboven.

    Ik zal verslag uitbrengen als ik iets werken

    tl;dr: ik ook!

    • geweldig werk! Ik nam ook deze oplossing een stap verder door de uitvoering van een “ApplicationPusher” dat is een applicatie niveau base class voor al mijn pusher-controllers. Dit voegt ondersteuning voor dingen zoals van de sessies(current_user) en autorisatie(via DeclarativeAuthorization): gist.github.com/synth/6170072
    • Ik ben met behulp van deze oplossing nu, en het werkt echt geweldig!
    • Gewoon het toevoegen van een opmerking dat het nuttig url gekoppeld aan de bovenkant van het commentaar is veranderd: amberbit.com/blog/2011/12/27/… en ook toevoegen dat ik heb gevonden is dit een nuttig: gist.github.com/juggy/977181
    • Het is niet absoluut noodzakelijk om een controller. Zie mijn antwoord hieronder.
    • ApplicationController.new.render_to_string(partial: 'messages/any', ...) is veel beter
    • rails 4.x-oplossing stackoverflow.com/questions/18263220/…

  2. 58

    Ik gewoon dit doen:

    ApplicationController.new.render_to_string(partial: 'messages/any', locals: { variable: 'value' })
    • Voor sommige reden, kon ik niet gebruiken link_to in mijn boventonen met deze oplossing. De fout was undefined method host’ voor nul:NilClass`
    • Ik ben het passeren van de controller aan op de model-methode die oproepen maken en te gebruiken voor het aanroepen van de render_to_string methode. Dat doet oplossen van uw probleem?
    • cache gooit undefined method host' for nil:NilClass te
    • Ik gebruik nog steeds, maar hebben nooit een fan geweest van de “link_to” – altijd mijn routing eenvoudig genoeg dat het meer zin om elk object weet dat het de url (ik definieer model.de url in een superklasse), dus in plaats van link_to(@gebruikersnaam), ik gebruik een [email protected] – imo routing helpers was een van de grote gebieden rails gedwaald. Uiteindelijk, sorry, ik weet niet waarom dit zou breken – je zou kunnen proberen het te rommelen met set_instance_variable(‘@controller, controller), maar dan zou je moeten stellen aan een draad wereldwijd te slaan controller + kan net zo goed dingen doen “recht” in de eerste plaats als het eenmaal wordt dat lelijk.
    • Dit werkte voor mij: ActionController::Base.new.render_to_string – zonder ApplicationController fouten.
    • is het jullie gelukt om dat te doen terwijl de uitbreiding van ApplicationHelper?

  3. 37

    Rails 5-weg

    In Rails 5 rendering buiten een controller werd vrij eenvoudig door uitgevoerd render controller methode van de klasse:

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

    Bij het aanroepen van render buiten van een controller, kan men toewijzen instantievariabelen via assigns optie en gebruik maken van andere opties beschikbaar zijn binnen een controller:

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

    Verzoek omgeving kunnen op maat worden gemaakt, hetzij via standaard opties

    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'

    of expliciet door het initialiseren van een nieuwe renderer

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

    Hoop dat het helpt.

    • Ik krijg ontbreekt gedeeltelijk fouten voor deze methode, omdat het er van binnen uitziet ‘app/views/application’ voor partiële protheses, tenzij ik waardoor ze met hun volledige pad. Ik heb de <%= renderen ‘/dingen/mypartial’ %> in plaats van slechts <%= renderen ‘mypartial’ %>. Als alternatief kan ik gebruik ThingsController.renderen, maar dat lijkt een soort rommelig. Weet iemand hoe het weer weg? #view_paths gewoon punten naar /app/views dus dat is het niet.
    • geweldig antwoord. ik vraag me af waarom mijn asset_host is example.org zelfs tho ik http_host: ActionMailer::Base.default_url_options[:host]
  4. 24

    Kunt u gebruik maken van ActionView direct en renderen van partiële protheses tot string zonder een controller. Ik vind dat patroon handig voor het maken van modellen die in te kapselen enkele javascript generatie, bijvoorbeeld.

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

    Dan, zet gewoon je _test.html.erb in u map weergeven en probeer het uit!

    • Simpel en gemakkelijk, de beste antwoord
    • Hehe, ik heb net gegoogled deze vraag mezelf. Dank u zelf uit het verleden!
    • Hoewel ik weet niet meer precies hoe ik dat deed, je hoeft alleen maar te zijn de helpers in uw ActionView::Base object
    • als u het opslaan van de actionview basis exemplaar als “printer” je kunt doen printer.verlengen(Rails.toepassing.helpers)
    • Ik ben niet in staat om toe te voegen een de plaatselijke bevolking om dit object.
  5. 2

    Ik ben er tamelijk zeker van dat de antwoorden die u zoekt, liggen binnen Knutselen Rails Applicaties waar Jose Valim gaat in detail in op hoe en waarom je zou willen om te renderen uitzicht direct vanuit uw db

    Sorry ik kan u niet meer helpen, maar ik ben net begonnen met het lezen van het zelf vanavond.

    U kan vinden wat hulp hier – het is een blog over het doen van dit soort dingen, zij het met gebruik van andere methoden dan de jouwe

  6. 2

    de “juiste” manier om dit te doen is om een object in seriële vorm(json), en vervolgens de weergave te gaan zodra het evenement is ontvangen. Misschien wilt u gebruik maken van het Stuur naar het renderen van het object.

    Edit: ik oorspronkelijk geschreven over het hoe, ondanks mijn antwoord, ik was van plan om uw voorbeeld volgen. Maar ik besefte dat er een ENORME gotcha met uw aanpak als het gaat om push-notificaties.

    In uw probleem, je doet push-berichten naar een gebruiker. Voor mij, ik was de omroep uit naar een groep gebruikers. Dus ik was van plan om het renderen van html met een vermoeden van een “current_user” en alles wat daarbij komt kijken(zoals logica, machtigingen, etc.). Dit is GEEN BUENO als elke push notificatie ontvangen zullen worden door een andere “huidige gebruiker”.

    Dus echt, je moet gewoon terug te sturen de gegevens, en laat elke individuele mening aan te pakken.

    • Dit is niet zeer droge, tenzij u met js te maken van al uw sjablonen.
  7. 0

    Moet je bellen, maken van methoden van een controller. Dus, in dit geval kunt u dit melden aan de controller die het object heeft gemaakt en de controller kan dan het renderen van het uitzicht. Ook, omdat je te maken kan maar een keer, ik denk dat je kunt wachten totdat uw server side bewerkingen te voltooien vooraleer de render.

    • Dankzij hoe zou ik renderen met de controller en stel deze in op de inhoud in het model, zoals hierboven weergegeven?
    • Kunt u het bijwerken van de vraag om meer specifiek te zijn over wat je wilt bereiken? jaydel terecht opmerkt dat dit niet de Rails manier van doen.
  8. 0

    De render methoden die zijn gedefinieerd op de ActiveController klasse en haar nageslacht. Inherent u hebt geen toegang tot het op het model, noch is het een methode van de klasse, zodat u niet kunt gebruiken zonder een exemplaar van de controller.

    Ik heb nooit geprobeerd om het concretiseren van een controller voor het uitdrukkelijke doel van het gewoon stringifying een gedeeltelijke, maar als je kunt krijgen van uw handen op een controller, render_to_string lijkt de weg te gaan.

    Ik zal doorklinken in door te zeggen dat als je naar beneden gaat dit pad je neemt RoR “off the Rails”. Dit is een schending van MVC en fundamenteel slechte ontwerp van het programma.Dit betekent niet dat ik denk dat je een slecht persoon 😛 Soms is het leven drijft ons uit de rails, om zo te spreken.

    Ik kan niet spreken over de gegevens die aan de basis van je om dit te doen, maar ik zou raden u nadenken over je aanpak.

    • bedankt voor het terug dringen. Ik weet niet hoe ik het anders om dit werk te krijgen. Ik ben met behulp van de drukknop gem(github.com/pusher/pusher-gem). Activeert wanneer het model heeft een nieuwe record toegevoegd. Het is er in het model waar ik willen duwen het nieuwe object. Weet u niet zeker hoe ik dat kan doen buiten het model?
  9. 0

    Heb ik gemaakt van een gist voor.

    Ik moest iets dergelijks, waar de modellen niet per se (of in mijn geval, ooit) bijgewerkt via een controller, dus de logica niet kunt zitten.

    Gemaakt van een server-push-based controller:

    https://gist.github.com/4707055

  10. 0

    Rails 6.0.0 compatibel beantwoorden, omdat ik uiteindelijk op deze pagina bij het zoeken naar een oplossing:

    lookup_context = ActionView::LookupContext.new(Rails.configuration.paths["app/views"])
    renderer = ActionView::Base.new(lookup_context)
    renderer.extend(Rails.application.helpers)
    renderer.render \
      template: "foo/bar",
      formats: [:html],
      handlers: [:erb],
      locals: { user: User.new }

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *