在控制器/邮件程序轨道之外渲染HTML模板

时间:2018-12-01 15:57:19

标签: ruby-on-rails templates ruby-on-rails-5 renderer

我遇到了在控制器(服务/ lib目录下的类)之外呈现HTML模板的情况,我经历了https://api.rubyonrails.org/classes/ActionController/Renderer.html

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

是否将所有实例变量传递给“仅呈现方法”选项以获取对view(html模板)中的实例变量的访问权限,或者是否具有任何其他可访问所有实例变量的配置?。

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

如果确实传递了模板/布局文件中正在使用的所有实例变量,则在添加新变量时需要检查所有时间。我已经参考了动作控制器和动作视图的流程,并得到了这个How are Rails instance variables passed to views?,对于非控制器类,我如何拥有这个流程?

1 个答案:

答案 0 :(得分:0)

答案的简短版本是:

  

您的服务应作为“演示者”本地传递,而您的部分应将变量委派回您的服务。

答案更长,但首先要清理嗓子...

在进入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。它本身必须传递,而我只需要确保服务对象能够响应在部分对象内进行的所有调用。