TL;DR
class DebugController < ActionController::Base
def render_foo(argv = nil)
@foo = 'Foo'
render_to_string template: 'foos/show'
end
end
DebugController.new.render_foo
=> "<!DOCTYPE html>\n<html lang='ja'>\n<head>\n<meta charset='UTF-8'>\n<title>Foo</title>\n</meta>\n</head>\n<body>\n<h1>Foo</h1>\n</body>\n</html>\n"
2022-12-26最新版
ac = ApplicationController.new
ac.instance_variable_set(:@foo, 'Foo') # インスタンス変数をインジェクション
ac.render_to_string('foos/show', layout: false)
=> "<!DOCTYPE html>\n<html lang='ja'>\n<head>\n<meta charset='UTF-8'>\n<title>Foo</title>\n</meta>\n</head>\n<body>\n<h1>Foo</h1>\n</body>\n</html>\n"
詳しくは: [続] Rails Consoleなど任意の場所、Inlineで任意のViewを任意条件でRenderする
経緯
何をしたい
仕事上でとある特別のCSVをConsoleで出したいが、該当CSVはViewの中の index.csv.csvbuilder
より作成されていて、Rails Consoleでの再現は極めて難しいでした。
わかったこと
いろいろ調査した結果、Controller
をnew
でインスタンスを作成し、Action
を呼び出すことが可能だとわかりました。
また、Renderingの結果を次の処理に渡したい時、render_to_string
を使えば、文字列として返してくれます。
やり方
まずは、ActionController::Base
を継承して、ダミーのClassを作成します。
もちろん、Helperを利用したり、他のControllerのメソッドを使いたいときは、ApplicationController
やその他コントローラーを継承できます。
class DebugController < ApplicationController
end
そして、レンダリングしたいViewを指定して、Actionを作成します。
ここのActionは引数を代入できる反面、普段使っているparams
という変数は存在しません。
また、Viewに表示したいインスタンス変数も、ここで定義します。
それに一般のコントローラーと同様に、template
をviews/
配下のファイルを指定できます。
class DebugController < ApplicationController
def render_foo(argv = '')
@foo = argv
render_to_string template: "foos/show"
end
end
(下記のfoos/show
が下記のViewとして進みます)
doctype html
html lang="ja"
head
meta charset="UTF-8"
title = @foo
body
h1 = @foo
最後は、上記 DebugController
をRails Consoleに流して、インスタンス化し、アクションを呼び出します。
DebugController.new.render_foo('Foo')
Rendering foos/show.html.slim
Rendered foos/show.html.slim (Duration: 8.1ms | Allocations: 6817)
=> "<!DOCTYPE html>\n<html lang='ja'>\n<head>\n<meta charset='UTF-8'>\n<title>Foo</title>\n</meta>\n</head>\n<body>\n<h1>Foo</h1>\n</body>\n</html>\n"