From 4dce874028e7dbb782f86a4cc83ead8565c4203c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E4=B8=AD=E6=99=8B=E5=A4=AA=E6=9C=97?= Date: Tue, 12 Feb 2019 20:33:32 +0900 Subject: [PATCH] Added support for runtime `append_view_path` and `prepend_view_path` instance methods in controllers --- app/views/_xray_bar.html.erb | 2 + lib/xray/engine.rb | 21 ++++++ .../app/controllers/application_controller.rb | 18 ++++++ .../application/additional_view.html.erb | 5 ++ .../views/variant_2/layouts/another.html.erb | 18 ++++++ spec/xray/engine_spec.rb | 52 +++++++++++++++ spec/xray/xray_bar_spec.rb | 64 ++++++++++++++++--- 7 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 spec/dummy/app/views/variant_2/application/additional_view.html.erb create mode 100644 spec/dummy/app/views/variant_2/layouts/another.html.erb diff --git a/app/views/_xray_bar.html.erb b/app/views/_xray_bar.html.erb index eae6980..618e4cf 100644 --- a/app/views/_xray_bar.html.erb +++ b/app/views/_xray_bar.html.erb @@ -8,6 +8,8 @@ <% end %> <% if Xray.request_info[:view] && Xray.request_info.fetch(:controller, {})[:name] != "Rails::InfoController" %> + <% lookup_context.view_paths.unshift(*Xray.request_info.fetch(:view_paths, {}).fetch(:prepend, [])) %> + <% lookup_context.view_paths.push(*Xray.request_info.fetch(:view_paths, {}).fetch(:append, [])) %> <% layout_path = lookup_context.find(Xray.request_info[:view][:layout]).identifier %> diff --git a/lib/xray/engine.rb b/lib/xray/engine.rb index ea0ebee..943ce52 100644 --- a/lib/xray/engine.rb +++ b/lib/xray/engine.rb @@ -42,6 +42,27 @@ def render_with_xray(*args, &block) xray_method_alias :render end + ActionView::ViewPaths.class_eval do + extend Xray::Aliasing + + def append_view_path_with_xray(args) + source = prepend_view_path_without_xray(args) + Xray.request_info[:view_paths] ||= {} + Xray.request_info[:view_paths][:append] ||= [] + Xray.request_info[:view_paths][:append] += [*args] + source + end + xray_method_alias :append_view_path + def prepend_view_path_with_xray(args) + source = prepend_view_path_without_xray(args) + Xray.request_info[:view_paths] ||= {} + Xray.request_info[:view_paths][:prepend] ||= [] + Xray.request_info[:view_paths][:prepend] += [*args] + source + end + xray_method_alias :prepend_view_path + end + # Sprockets preprocessor interface which supports all versions of Sprockets. # See: https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors class JavascriptPreprocessor diff --git a/spec/dummy/app/controllers/application_controller.rb b/spec/dummy/app/controllers/application_controller.rb index 99c934d..8d6ab63 100644 --- a/spec/dummy/app/controllers/application_controller.rb +++ b/spec/dummy/app/controllers/application_controller.rb @@ -1,5 +1,6 @@ class ApplicationController < ActionController::Base protect_from_forgery + layout 'another', only: %i(appended_view_path appended_view_path_without_xray prepended_view_path prepended_view_path_without_xray) def root end @@ -12,4 +13,21 @@ def non_html def made_with_haml respond_to :json end + + def appended_view_path + append_view_path [Rails.root.join('app', 'views', 'variant_1'), Rails.root.join('app', 'views', 'variant_2')] + render :additional_view + end + def prepended_view_path + prepend_view_path [Rails.root.join('app', 'views', 'variant_1'), Rails.root.join('app', 'views', 'variant_2')] + render :additional_view + end + def appended_view_path_without_xray + append_view_path_without_xray [Rails.root.join('app', 'views', 'variant_1'), Rails.root.join('app', 'views', 'variant_2')] + render :additional_view + end + def prepended_view_path_without_xray + prepend_view_path_without_xray [Rails.root.join('app', 'views', 'variant_1'), Rails.root.join('app', 'views', 'variant_2')] + render :additional_view + end end diff --git a/spec/dummy/app/views/variant_2/application/additional_view.html.erb b/spec/dummy/app/views/variant_2/application/additional_view.html.erb new file mode 100644 index 0000000..64ef56d --- /dev/null +++ b/spec/dummy/app/views/variant_2/application/additional_view.html.erb @@ -0,0 +1,5 @@ +
+ Element in the additional view. +
+ +<%= render partial: 'simple_partial' %> diff --git a/spec/dummy/app/views/variant_2/layouts/another.html.erb b/spec/dummy/app/views/variant_2/layouts/another.html.erb new file mode 100644 index 0000000..a963665 --- /dev/null +++ b/spec/dummy/app/views/variant_2/layouts/another.html.erb @@ -0,0 +1,18 @@ + + + + Xray + <%= stylesheet_link_tag "application", :media => "all" %> + <%= javascript_include_tag "application" %> + <%= csrf_meta_tags %> + + + +
+ Layout in the additional view path. +
+ +<%= yield %> + + + diff --git a/spec/xray/engine_spec.rb b/spec/xray/engine_spec.rb index a6e5009..50d23b6 100644 --- a/spec/xray/engine_spec.rb +++ b/spec/xray/engine_spec.rb @@ -46,5 +46,57 @@ expect(subject.render(*xray_enabled_render_args)).to eql(nil) end end + + context 'ActionView::ViewPaths monkeypatch' do + context 'on adding single variant path' do + let(:view_path_arg) { Rails.root.join('app', 'views', 'variant_1') } + + context '#append_view_path' do + subject { Xray.request_info[:view_paths][:append] } + + it 'should append additional view paths to Xray.request_info[:view_paths][:append]' do + allow_any_instance_of(ActionView::LookupContext).to receive(:append_view_path_without_xray).with(view_path_arg) + allow_any_instance_of(ActionView::LookupContext).to receive(:append_view_path).with(view_path_arg) + ActionController::Base.new.append_view_path view_path_arg + is_expected.to include(view_path_arg) + end + end + context '#prepend_view_path' do + subject { Xray.request_info[:view_paths][:prepend] } + + it 'should prepend additional view paths to Xray.request_info[:view_paths][:prepend]' do + allow_any_instance_of(ActionView::LookupContext).to receive(:prepend_view_path_without_xray).with(view_path_arg) + allow_any_instance_of(ActionView::LookupContext).to receive(:prepend_view_path).with(view_path_arg) + ActionController::Base.new.prepend_view_path(view_path_arg) + is_expected.to include(view_path_arg) + end + end + end + + context 'on adding arrayed variant path' do + let(:view_path_arg) { [Rails.root.join('app', 'views', 'variant_1'), Rails.root.join('app', 'views', 'variant_2')] } + + context '#append_view_path' do + subject { Xray.request_info[:view_paths][:append] } + + it 'should append additional view paths to Xray.request_info[:view_paths][:append]' do + allow_any_instance_of(ActionView::LookupContext).to receive(:append_view_path_with_xray).with(view_path_arg) + allow_any_instance_of(ActionView::LookupContext).to receive(:append_view_path).with(view_path_arg) + ActionController::Base.new.append_view_path view_path_arg + is_expected.to include(*view_path_arg) + end + end + context '#prepend_view_path' do + subject { Xray.request_info[:view_paths][:prepend] } + + it 'should prepend additional view paths to Xray.request_info[:view_paths][:prepend]' do + allow_any_instance_of(ActionView::LookupContext).to receive(:prepend_view_path_without_xray).with(view_path_arg) + allow_any_instance_of(ActionView::LookupContext).to receive(:prepend_view_path).with(view_path_arg) + ActionController::Base.new.prepend_view_path view_path_arg + is_expected.to include(*view_path_arg) + end + end + end + end end diff --git a/spec/xray/xray_bar_spec.rb b/spec/xray/xray_bar_spec.rb index e9b7ba6..1d499d6 100644 --- a/spec/xray/xray_bar_spec.rb +++ b/spec/xray/xray_bar_spec.rb @@ -1,17 +1,65 @@ require 'spec_helper' -describe "Xray Bar" do - before { visit '/' } +describe "Xray Bar", type: :request do + subject { find("#xray-bar") } - it "includes the controller and action" do - find('#xray-bar').should have_text('ApplicationController#root') + context "includes an #xray-bar element" do + before { visit '/' } + + it "with the controller and action" do + is_expected.to have_text('ApplicationController#root') + end + + it "with the layout used" do + is_expected.to have_text('application.html.erb') + end + + it "with the view rendered" do + is_expected.to have_text('root.html.erb') + end end - it "includes the layout used" do - find('#xray-bar').should have_text('application.html.erb') + context "with views in paths" do + context "appended by #append_view_path_without_xray" do + let(:path) { "/appended_view_path_without_xray" } + + it "should not resolve the layout location" do + get path + expect(response).to have_http_status(500) + end + end + + context "prepended by #prepend_view_path_without_xray" do + let(:path) { "/prepended_view_path_without_xray" } + + it "should not resolve the layout location" do + get path + expect(response).to have_http_status(500) + end + end end - it "includes the view rendered" do - find('#xray-bar').should have_text('root.html.erb') + context "with views in paths" do + let(:layout) { "another.html.erb" } + let(:view) { "additional_view.html.erb" } + before { visit path } + + context "appended by #append_view_path" do + let(:path) { "/appended_view_path" } + + it "should resolve the layout location" do + is_expected.to have_text(layout) + is_expected.to have_text(view) + end + end + + context "prepended by #prepend_view_path" do + let(:path) { "/prepended_view_path" } + + it "should resolve the layout location" do + is_expected.to have_text(layout) + is_expected.to have_text(view) + end + end end end