Railsアプリケーション開発においてデザイナの方とかと並行して開発していると、
htmlは既にできてて、モデルとかコントローラとかまだちゃんと設計できてないけど、アプリケーション上で表示したい、ってことがあります。
public以下に配置してもいいんですが、application.html.erbのテンプレートの恩恵はちゃんと受けたいし、後でController実装するときに移動するの面倒だなとか、
ありますよね??
要件
こんなかんじです。
デザイナ側
- Railsアプリケーション中にhtmlを配置するだけで、表示できるようにしたい
- 黒い画面は触りたくない
- routes.rbも触りたくない
プログラマ側
- layouts以下のapplication.html.erbは反映させたい
- その他、グローバルに存在する変数とかセッションとかは残したい
- 後でControllerを実装するときに移動させたくない
解決策
Viewを表示するにはRoutingとControllerが必須ですよね。
ということで、routingはViews以下のディレクトリに存在するファイルを読んで追加するようにし、
コントローラは共通のものを作って、パラメータで表示するViewを指定するようにしてみました。
コード
NoControllerApp::Application.routes.draw do
exclude_dir = ["layouts"]
anonymous_dir = []
Dir::glob(File.join(Rails.root.to_s, "/app/views/*/")).map{|f| anonymous_dir << f.split("/").last }
(anonymous_dir - exclude_dir).each do |dir|
get "#{dir}" => "anonymous#index", :defaults => {:directory => "#{dir}"}
end
end
app/views/以下に置かれたlayouts以外のディレクトリを対象とし、Routingに追加します。
これだと、Layoutとか通常の手段で追加されたディレクトリとかも対象になってしまうので、それらはexclude_dirに追加して対象外とします。
viewのみ存在するhtmlを表示するためのコントローラとして"AnonymousController"という共通で呼ばれるコントローラを作成し、そこで描画するViewを制御します。
class AnonymousController < ApplicationController
def index
render "#{params[:directory]}/index"
end
end
動作確認用のファイルを作ります。
mkdir app/views/foo
touch app/views/foo/index.html.erb
mkdir app/views/bar
touch app/views/bar/index.html.erb
この状態でrake routesすると以下のようになります。
$ rake routes
Prefix Verb URI Pattern Controller#Action
bar GET /bar(.:format) anonymous#index {:directory=>"bar"}
foo GET /foo(.:format) anonymous#index {:directory=>"foo"}
あとは、localhost:3000/foo/にアクセスすれば表示されます。
その他
まぁあくまで開発中に使う機能ですね。
Routingの設定がハードコードじみてるので、まだまだ改良の余地はありそうですが、
とりあえず要件は満たせたかなーと思っています。
もっと良いやり方があれば是非教えて下さい!