Рендеринг HTML шаблона за пределами контроллера / рельсов Mailer - PullRequest
0 голосов
/ 01 декабря 2018

У меня есть ситуация для рендеринга шаблона HTML вне контроллера (класс в каталоге service / lib), я прошел через https://api.rubyonrails.org/classes/ActionController/Renderer.html

@template = ApplicationController.render(
        template: 'template',
        layout: mailer_template,
    )

Передает все переменные экземпляра в рендеропция только метода, чтобы получить доступ к переменным экземпляра в представлении (шаблон HTML) или любые другие конфигурации, доступные для доступа ко всем переменным экземпляра?.

FooController.render :action, locals: { ... }, assigns: { ... }

Если мы действительно передадим все переменные экземпляра, которыеиспользуются в файле шаблона / макета, нам нужно проверять все время, когда мы добавляем новые переменные.Я сослался на поток контроллера действий и представление действия и получил это Как переменные экземпляра Rails передаются в представления? , как мне получить этот поток для неконтроллерного класса?

1 Ответ

0 голосов
/ 01 декабря 2018

Краткая версия ответа:

Ваш сервис должен выдавать себя за локального 'ведущего', а ваш частичный должен делегировать переменные обратно вашему сервису.

Есть более длинный ответ, но сначала немного прочистилось горло ...

Я начал делать бит "рендеринга в любом месте", прежде чем попасть в Rails 5,так что мой подход выглядит немного иначе, чем то, что вы в конечном итоге делаете.Но, возможно, это поможет.

А потом какой-нибудь фон ...

У меня есть модуль (что-то вроде ActsAs::Rendering), который включает метод экземпляра, называемый render_partial это выглядит примерно так:

module ActsAs::Rendering
  def render_partial(file_name)
    file_name = file_name.to_s
    render(partial: file_name, locals: {presenter: self})
  end
end

Это нечто большее, но я думаю, что это даст вам идею.Важный бит (к которому мы вернемся позже) заключается в том, что self передается как presenter.

Затем в моем сервисе я могу сделать что-то вроде:

class BatchMailerService < ApplicationService

  def call
    render_partial :my_cool_partial
  end

  def tell_method_something_good
    "Tell me that you like it, yeah."
  end

end

Я думаю, с Rails 5, вы будете использовать этот FooController.render :action, locals: { ... } бит.Но, как я уже сказал, я еще не удосужился заняться этим Rails 5, поэтому я не уверен.

Естественно, у меня есть ApplicationService (ниже app/services), который выглядит примерно так:

class ApplicationService
  include ActsAs::Rendering

  attr_accessor *%w(
    args
  ).freeze

  class << self 

    def call(args={})
      new(args).call
    end        

  end  # Class Methods

  #==============================================================================================
  # Instance Methods
  #==============================================================================================

    def initialize(args={})
      @args = args
      assign_args
    end

  private

    def assign_args
      args.each do |k,v|
        class_eval do 
          attr_accessor k
        end
        send("#{k}=",v)
      end
    end        

end

Сказав все это ...

:my_cool_partial может выглядеть примерно так:

"my_cool_partial.html.haml"

- @presenter = local_assigns[:presenter] if local_assigns[:presenter]

#tell-me-something-good-container
  = @presenter.tell_me_something_good

Теперь, еслиЯ делаю:

BatchMailerService.call    

Я получу что-то вроде:

<div id="tell-me-something-good-container">
  Tell me that you like it, yeah.
</div>

Таким образом, объекту службы не нужно передавать длинный список locals.Он просто должен пройти сам по себе, и я просто должен убедиться, что сервисный объект отвечает на любые вызовы, сделанные внутри партиала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...