deface 1.5.2 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,10 +48,8 @@ module Deface
48
48
  end
49
49
  end
50
50
 
51
- if Rails.gem_version < Gem::Version.new('6.0.0')
52
- #prevents any caching by rails in development mode
53
- details[:updated_at] = Time.now
54
- end
51
+ # Prevents any caching by rails in development mode.
52
+ details[:updated_at] = Time.now if Deface.before_rails_6?
55
53
 
56
54
  source = doc.to_s
57
55
 
@@ -57,13 +57,7 @@ module Deface
57
57
  Deface::DSL::Loader.register
58
58
 
59
59
  # check all railties / engines / extensions / application for overrides
60
- railties = if Rails.version >= "4.0"
61
- app.railties._all
62
- else
63
- app.railties.all
64
- end
65
-
66
- railties.dup.push(app).each do |railtie|
60
+ app.railties._all.dup.push(app).each do |railtie|
67
61
  next unless railtie.respond_to? :root
68
62
  load_overrides(railtie)
69
63
  end
@@ -89,11 +83,9 @@ module Deface
89
83
  paths ||= ["app/overrides"]
90
84
 
91
85
  paths.each do |path|
92
- if Rails.version[0..2] >= "3.2"
93
- # add path to watchable_dir so Rails will call to_prepare on file changes
94
- # allowing overrides to be updated / reloaded in development mode.
95
- Rails.application.config.watchable_dirs[root.join(path).to_s] = [:rb, :deface]
96
- end
86
+ # add path to watchable_dir so Rails will call to_prepare on file changes
87
+ # allowing overrides to be updated / reloaded in development mode.
88
+ Rails.application.config.watchable_dirs[root.join(path).to_s] = [:rb, :deface]
97
89
 
98
90
  Dir.glob(root.join path, "**/*.rb") do |c|
99
91
  Rails.application.config.cache_classes ? require(c) : load(c)
@@ -0,0 +1,5 @@
1
+ module Deface
2
+ class DefaceError < StandardError; end
3
+
4
+ class NotSupportedError < DefaceError; end
5
+ end
@@ -211,28 +211,22 @@ module Deface
211
211
 
212
212
  private
213
213
 
214
- # check if method is compiled for the current virtual path
215
- #
216
- def expire_compiled_template
217
- if Gem.loaded_specs["rails"].version < Gem::Version.new("6.0.0.beta1")
218
- if compiled_method_name = ActionView::CompiledTemplates.instance_methods.detect { |name| name =~ /#{args[:virtual_path].gsub(/[^a-z_]/, '_')}/ }
219
- #if the compiled method does not contain the current deface digest
220
- #then remove the old method - this will allow the template to be
221
- #recompiled the next time it is rendered (showing the latest changes)
222
-
223
- unless compiled_method_name =~ /\A_#{self.class.digest(:virtual_path => @args[:virtual_path])}_/
224
- ActionView::CompiledTemplates.send :remove_method, compiled_method_name
225
- end
226
- end
227
- else
228
- if compiled_method_name = ActionDispatch::DebugView.instance_methods.detect { |name| name =~ /#{args[:virtual_path].gsub(/[^a-z_]/, '_')}/ }
229
- unless compiled_method_name =~ /\A_#{self.class.digest(:virtual_path => @args[:virtual_path])}_/
230
- ActionDispatch::DebugView.send :remove_method, compiled_method_name
231
- end
232
- end
233
- end
214
+ # Check if method is compiled for the current virtual path.
215
+ #
216
+ # If the compiled method does not contain the current deface digest
217
+ # then remove the old method - this will allow the template to be
218
+ # recompiled the next time it is rendered (showing the latest changes).
219
+ def expire_compiled_template
220
+ virtual_path = args[:virtual_path]
221
+
222
+ method_name = Deface.template_class.instance_methods.detect do |name|
223
+ name =~ /#{virtual_path.gsub(/[^a-z_]/, '_')}/
234
224
  end
235
225
 
226
+ if method_name && method_name !~ /\A_#{self.class.digest(virtual_path: virtual_path)}_/
227
+ Deface.template_class.send :remove_method, method_name
228
+ end
229
+ end
236
230
  end
237
231
 
238
232
  end
@@ -36,19 +36,15 @@ module Deface
36
36
  initializer "deface.tweak_eager_loading", :before => :set_load_path do |app|
37
37
 
38
38
  # application
39
- app.config.eager_load_paths = app.config.eager_load_paths.reject { |path| path.to_s =~ /app\/overrides\z/ }
39
+ tweak_eager_loading(app)
40
40
 
41
41
  # railites / engines / extensions
42
- railties = if Rails.version >= "4.0"
43
- app.railties._all
44
- else
45
- app.railties.all
46
- end
47
-
48
- railties.each do |railtie|
42
+ app.railties._all.each do |railtie|
49
43
  next unless railtie.respond_to?(:root) && railtie.config.respond_to?(:eager_load_paths)
50
- railtie.config.eager_load_paths = railtie.config.eager_load_paths.reject { |path| path.to_s =~ /app\/overrides\z/ }
44
+
45
+ tweak_eager_loading(railtie)
51
46
  end
47
+
52
48
  end
53
49
 
54
50
  # sets up deface environment and requires / loads all
@@ -87,5 +83,15 @@ module Deface
87
83
  end
88
84
  end
89
85
 
86
+ private
87
+
88
+ def tweak_eager_loading(railtie)
89
+ paths_to_reject = railtie.config.eager_load_paths.select { |path| path.to_s =~ /app\/overrides\z/ }
90
+ railtie.config.eager_load_paths = railtie.config.eager_load_paths.reject { |path| path.in?(paths_to_reject) }
91
+
92
+ if Rails.configuration.respond_to?(:autoloader) && Rails.configuration.autoloader == :zeitwerk
93
+ Rails.autoloaders.each { |autoloader| autoloader.ignore(*paths_to_reject) }
94
+ end
95
+ end
90
96
  end
91
97
  end
@@ -1,32 +1,55 @@
1
1
  module Deface
2
2
  module TemplateHelper
3
+ def self.lookup_context
4
+ @lookup_context ||= ActionView::LookupContext.new(
5
+ ActionController::Base.view_paths, {:formats => [:html]}
6
+ )
7
+ end
3
8
 
4
9
  # used to find source for a partial or template using virtual_path
5
- def load_template_source(virtual_path, partial, apply_overrides=true)
10
+ def load_template_source(virtual_path, partial, apply_overrides=true, lookup_context: Deface::TemplateHelper.lookup_context)
6
11
  parts = virtual_path.split("/")
7
- prefix = []
12
+
8
13
  if parts.size == 2
9
- prefix << ""
14
+ prefix = ""
10
15
  name = virtual_path
11
16
  else
12
- prefix << parts.shift
17
+ prefix = parts.shift
13
18
  name = parts.join("/")
14
19
  end
15
20
 
16
- #this needs to be reviewed for production mode, overrides not present
17
- Rails.application.config.deface.enabled = apply_overrides
18
- @lookup_context ||= ActionView::LookupContext.new(ActionController::Base.view_paths, {:formats => [:html]})
19
- view = @lookup_context.disable_cache do
20
- @lookup_context.find(name, prefix, partial)
21
- end
21
+ view = lookup_context.disable_cache { lookup_context.find(name, [prefix], partial) }
22
22
 
23
- if view.handler.to_s == "Haml::Plugin"
24
- Deface::HamlConverter.new(view.source).result
25
- elsif view.handler.class.to_s == "Slim::RailsTemplate"
26
- Deface::SlimConverter.new(view.source).result
27
- else
28
- view.source
23
+ source =
24
+ if view.handler.to_s == "Haml::Plugin"
25
+ Deface::HamlConverter.new(view.source).result
26
+ elsif view.handler.class.to_s == "Slim::RailsTemplate"
27
+ Deface::SlimConverter.new(view.source).result
28
+ else
29
+ view.source
30
+ end
31
+
32
+ if apply_overrides
33
+ begin
34
+ # This needs to be reviewed for production mode, overrides not present
35
+ original_enabled = Rails.application.config.deface.enabled
36
+ Rails.application.config.deface.enabled = apply_overrides
37
+
38
+ if (syntax = Deface::ActionViewExtensions.determine_syntax(view.handler))
39
+ details = {
40
+ locals: view.instance_variable_get(:@locals),
41
+ format: view.instance_variable_get(:@format),
42
+ variant: view.instance_variable_get(:@variant),
43
+ virtual_path: view.instance_variable_get(:@virtual_path),
44
+ }
45
+ source = Deface::Override.apply(source, details, true, syntax)
46
+ end
47
+ ensure
48
+ Rails.application.config.deface.enabled = original_enabled
49
+ end
29
50
  end
51
+
52
+ source
30
53
  end
31
54
 
32
55
  #gets source erb for an element
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deface
4
+ VERSION = '1.7.0'
5
+
6
+ def gem_version
7
+ Gem::Version.new(VERSION)
8
+ end
9
+ end
@@ -1,101 +1,123 @@
1
1
  require 'spec_helper'
2
2
 
3
- module ActionView
4
- describe Template do
5
- include_context "mock Rails.application"
6
-
7
- describe "with no overrides defined" do
8
- before(:each) do
9
- @updated_at = Time.now - 600
10
- @template = ActionView::Template.new("<p>test</p>", "/some/path/to/file.erb", ActionView::Template::Handlers::ERB, {:virtual_path=>"posts/index", :format=>:html, :updated_at => @updated_at})
11
- #stub for Rails < 3.1
12
- unless defined?(@template.updated_at)
13
- allow(@template).to receive(:updated_at).and_return(@updated_at)
14
- end
15
- end
16
-
17
- it "should initialize new template object" do
18
- expect(@template.is_a?(ActionView::Template)).to eq(true)
19
- end
3
+ describe Deface::ActionViewExtensions do
4
+ include_context "mock Rails.application"
20
5
 
21
- it "should return unmodified source" do
22
- expect(@template.source).to eq("<p>test</p>")
23
- end
6
+ before after_rails_6: true do
7
+ skip "This spec is targeted at Rails v6+" if Deface.before_rails_6?
8
+ end
24
9
 
25
- it "should not change updated_at" do
26
- expect(@template.updated_at).to eq(@updated_at)
27
- end
10
+ before before_rails_6: true do
11
+ skip "This spec is targeted at Rails before v6+" unless Deface.before_rails_6?
12
+ end
28
13
 
14
+ let(:template) { ActionView::Template.new(
15
+ source,
16
+ path,
17
+ handler,
18
+ **options,
19
+ **(Deface.before_rails_6? ? {updated_at: updated_at} : {})
20
+ ) }
21
+
22
+ let(:source) { "<p>test</p>" }
23
+ let(:path) { "/some/path/to/file.erb" }
24
+ let(:handler) { ActionView::Template::Handlers::ERB }
25
+ let(:options) {{
26
+ virtual_path: virtual_path,
27
+ format: format,
28
+ locals: {}
29
+ }}
30
+ let(:format) { :html }
31
+ let(:virtual_path) { "posts/index" }
32
+
33
+ let(:updated_at) { Time.now - 600 }
34
+
35
+ describe "with no overrides defined" do
36
+ it "should initialize new template object" do
37
+ expect(template.is_a?(ActionView::Template)).to eq(true)
29
38
  end
30
39
 
31
- describe "with a single remove override defined" do
32
- before(:each) do
33
- @updated_at = Time.now - 300
34
- Deface::Override.new(:virtual_path => "posts/index", :name => "Posts#index", :remove => "p", :text => "<h1>Argh!</h1>")
35
- @template = ActionView::Template.new("<p>test</p><%= raw(text) %>", "/some/path/to/file.erb", ActionView::Template::Handlers::ERB, {:virtual_path=>"posts/index", :format=>:html, :updated_at => @updated_at})
36
- #stub for Rails < 3.1
37
- unless defined?(@template.updated_at)
38
- allow(@template).to receive(:updated_at).and_return(@updated_at + 500)
39
- end
40
- end
41
-
42
- it "should return modified source" do
43
- expect(@template.source).to eq("<%= raw(text) %>")
44
- end
45
-
46
- if Rails.gem_version >= Gem::Version.new('6.0.0')
47
- it "should not change updated_at" do
48
- expect(@template.updated_at).to eq(@updated_at)
49
- end
50
- else
51
- it "should change updated_at" do
52
- expect(@template.updated_at).to be > @updated_at
53
- end
54
- end
40
+ it "should return unmodified source" do
41
+ expect(template.source).to eq("<p>test</p>")
55
42
  end
56
43
 
57
- describe "method_name" do
58
- let(:template) { ActionView::Template.new("<p>test</p>", "/some/path/to/file.erb", ActionView::Template::Handlers::ERB, {:virtual_path=>"posts/index", :format=>:html, :updated_at => (Time.now - 100)}) }
44
+ it "should not change updated_at", :before_rails_6 do
45
+ expect(template.updated_at).to eq(updated_at)
46
+ end
47
+ end
59
48
 
60
- it "should return hash of overrides plus original method_name " do
61
- deface_hash = Deface::Override.digest(:virtual_path => 'posts/index')
49
+ describe "non erb or haml template" do
50
+ let(:source) { "xml.post => :blah" }
51
+ let(:path) { "/some/path/to/file.erb" }
52
+ let(:handler) { ActionView::Template::Handlers::Builder }
53
+ let(:updated_at) { Time.now - 100 }
54
+ let(:format) { :xml }
62
55
 
63
- expect(template.send(:method_name)).to eq("_#{Digest::MD5.new.update("#{deface_hash}_#{template.send(:method_name_without_deface)}").hexdigest}")
64
- end
56
+ before(:each) do
57
+ Deface::Override.new(virtual_path: "posts/index", name: "Posts#index", remove: "p")
58
+ end
65
59
 
66
- it "should alias original method_name method" do
67
- expect(template.send(:method_name_without_deface)).to match /\A__some_path_to_file_erb_+[0-9]+_+[0-9]+\z/
68
- end
60
+ it "should return unmodified source" do
61
+ expect(template.source).to eq("xml.post => :blah")
62
+ expect(template.source).not_to include("=&gt;")
69
63
  end
64
+ end
70
65
 
71
- describe "non erb or haml template" do
72
- before(:each) do
73
- Deface::Override.new(:virtual_path => "posts/index", :name => "Posts#index", :remove => "p")
74
- @template = ActionView::Template.new("xml.post => :blah", "/some/path/to/file.erb", ActionView::Template::Handlers::Builder, {:virtual_path=>"posts/index", :format=>:xml, :updated_at => (Time.now - 100)})
66
+ describe ".determine_syntax(handler)" do
67
+ let(:source) { "xml.post => :blah" }
68
+ let(:format) { :xml }
69
+
70
+ # Not so BDD, but it keeps us from making mistakes in the future for instance,
71
+ # we test ActionView::Template here with a handler == ....::Handlers::ERB,
72
+ # while in rails it seems it's an instance of ...::Handlers::ERB.
73
+ it "recognizes supported syntaxes" do
74
+ expectations = { Haml::Plugin => :haml,
75
+ ActionView::Template::Handlers::ERB => :erb,
76
+ ActionView::Template::Handlers::ERB.new => :erb,
77
+ ActionView::Template::Handlers::Builder => nil }
78
+ expectations.each do |handler, expected|
79
+ expect(template.is_a?(ActionView::Template)).to eq(true)
80
+ expect(described_class.determine_syntax(handler)).to eq(expected), "unexpected result for handler #{handler}"
75
81
  end
82
+ end
83
+ end
76
84
 
77
- it "should return unmodified source" do
78
- #if processed, source would include "=&gt;"
79
- expect(@template.source).to eq("xml.post => :blah")
85
+ describe '#render' do
86
+ let(:source) { "<p>test</p><%= raw(text) %>".inspect }
87
+ let(:local_assigns) { {text: "some <br> text"} }
88
+ let(:lookup_context) { ActionView::LookupContext.new(["#{__dir__}/views"]) }
89
+ let(:view) do
90
+ if Rails::VERSION::STRING >= '6.1'
91
+ ActionView::Base.with_empty_template_cache.new(lookup_context, {}, nil)
92
+ else
93
+ ActionView::Base.new(lookup_context)
80
94
  end
81
95
  end
96
+ let(:options) { {
97
+ virtual_path: virtual_path,
98
+ format: format,
99
+ locals: local_assigns.keys
100
+ } }
101
+
102
+ it 'renders the template modified by deface using :replace' do
103
+ Deface::Override.new(
104
+ virtual_path: virtual_path,
105
+ name: "Posts#index",
106
+ replace: "p",
107
+ text: "<h1>Argh!</h1>"
108
+ )
109
+
110
+ expect(template.render(view, local_assigns)).to eq(%{"<h1>Argh!</h1>some <br> text"})
111
+ end
82
112
 
83
- describe "#should_be_defaced?(handler) method" do
84
- #not so BDD, but it keeps us from making mistakes in the future
85
- #for instance, we test ActionView::Template here with a handler == ....::Handlers::ERB,
86
- #while in rails it seems it's an instance of ...::Handlers::ERB
87
- it "should be truthy only for haml/erb handlers and their instances" do
88
- expectations = { Haml::Plugin => true,
89
- ActionView::Template::Handlers::ERB => true,
90
- ActionView::Template::Handlers::ERB.new => true,
91
- ActionView::Template::Handlers::Builder => false }
92
- expectations.each do |handler, expected|
93
- @template = ActionView::Template.new("xml.post => :blah", "/some/path/to/file.erb", handler, {:virtual_path=>"posts/index", :format=>:xml, :updated_at => (Time.now - 100)})
94
- expect(@template.is_a?(ActionView::Template)).to eq(true)
95
- syntax = @template.send(:determine_syntax, handler)
96
- expect(@template.send(:should_be_defaced?, syntax)).to eq(expected), "unexpected result for handler "+handler.to_s
97
- end
98
- end
113
+ it 'renders the template modified by deface using :remove' do
114
+ Deface::Override.new(
115
+ virtual_path: virtual_path,
116
+ name: "Posts#index",
117
+ remove: "p",
118
+ )
119
+
120
+ expect(template.render(view, local_assigns)).to eq(%{"some <br> text"})
99
121
  end
100
122
  end
101
123
  end
@@ -19,8 +19,6 @@ module Deface
19
19
  Deface::Override.new(:virtual_path => "posts/new", :name => "Posts#new", :replace => "h1", :text => "<h1>argh!</h1>")
20
20
  end
21
21
 
22
- let(:railties_collection_accessor) { Rails.version >= "4.0" ? :_all : :all }
23
-
24
22
  describe ".overrides" do
25
23
 
26
24
  it "should return all overrides" do
@@ -37,7 +35,7 @@ module Deface
37
35
  before do
38
36
  allow(Rails.application).to receive_messages :root => Pathname.new(File.join(File.dirname(__FILE__), '..', "assets"))
39
37
  allow(Rails.application).to receive_messages :paths => {}
40
- allow(Rails.application).to receive_message_chain :railties, railties_collection_accessor => []
38
+ allow(Rails.application).to receive_message_chain :railties, :_all => []
41
39
 
42
40
  expect(Deface::DSL::Loader).to receive(:register)
43
41
  end
@@ -54,7 +52,7 @@ module Deface
54
52
  end
55
53
 
56
54
  it "should enumerate_and_load nil when railtie has no app/overrides path set" do
57
- allow(Rails.application).to receive_message_chain :railties, railties_collection_accessor => [double('railtie', :root => "/some/path")]
55
+ allow(Rails.application).to receive_message_chain :railties, :_all => [double('railtie', :root => "/some/path")]
58
56
 
59
57
  expect(Rails.application.config.deface.overrides).to receive(:enumerate_and_load).with(nil, Rails.application.root)
60
58
  expect(Rails.application.config.deface.overrides).to receive(:enumerate_and_load).with(nil, "/some/path")
@@ -62,7 +60,7 @@ module Deface
62
60
  end
63
61
 
64
62
  it "should enumerate_and_load path when railtie has app/overrides path set" do
65
- allow(Rails.application).to receive_message_chain :railties, railties_collection_accessor => [ double('railtie', :root => "/some/path", :paths => {"app/overrides" => ["app/some_path"] } )]
63
+ allow(Rails.application).to receive_message_chain :railties, :_all => [ double('railtie', :root => "/some/path", :paths => {"app/overrides" => ["app/some_path"] } )]
66
64
 
67
65
  expect(Rails.application.config.deface.overrides).to receive(:enumerate_and_load).with(nil, Rails.application.root)
68
66
  expect(Rails.application.config.deface.overrides).to receive(:enumerate_and_load).with(["app/some_path"] , "/some/path")
@@ -70,7 +68,7 @@ module Deface
70
68
  end
71
69
 
72
70
  it "should enumerate_and_load railties first, followed by the application iteslf" do
73
- allow(Rails.application).to receive_message_chain :railties, railties_collection_accessor => [ double('railtie', :root => "/some/path", :paths => {"app/overrides" => ["app/some_path"] } )]
71
+ allow(Rails.application).to receive_message_chain :railties, :_all => [ double('railtie', :root => "/some/path", :paths => {"app/overrides" => ["app/some_path"] } )]
74
72
 
75
73
  expect(Rails.application.config.deface.overrides).to receive(:enumerate_and_load).with(["app/some_path"] , "/some/path").ordered
76
74
  expect(Rails.application.config.deface.overrides).to receive(:enumerate_and_load).with(nil, Rails.application.root).ordered
@@ -79,7 +77,7 @@ module Deface
79
77
 
80
78
  it "should ignore railtie with no root" do
81
79
  railtie = double('railtie')
82
- allow(Rails.application).to receive_message_chain :railties, railties_collection_accessor => [railtie]
80
+ allow(Rails.application).to receive_message_chain :railties, :_all => [railtie]
83
81
 
84
82
  expect(railtie).to receive(:respond_to?).with(:root)
85
83
  expect(railtie).not_to receive(:respond_to?).with(:paths)
@@ -101,7 +99,7 @@ module Deface
101
99
 
102
100
  it "should keep a reference to which railtie/app defined the override" do
103
101
  allow(Rails.application).to receive_messages :root => assets_path, :paths => {"app/overrides" => ["dummy_app"] }
104
- allow(Rails.application).to receive_message_chain :railties, railties_collection_accessor => [ engine ]
102
+ allow(Rails.application).to receive_message_chain :railties, :_all => [ engine ]
105
103
 
106
104
  Rails.application.config.deface.overrides.load_all(Rails.application)
107
105
 
@@ -127,10 +125,8 @@ module Deface
127
125
  end
128
126
 
129
127
  it "should add paths to watchable_dir when running Rails 3.2" do
130
- if Rails.version[0..2] >= '3.2'
131
- Rails.application.config.deface.overrides.send(:enumerate_and_load, ["app/gold"], root)
132
- expect(Rails.application.config.watchable_dirs).to eq({"/some/path/app/gold" => [:rb, :deface] })
133
- end
128
+ Rails.application.config.deface.overrides.send(:enumerate_and_load, ["app/gold"], root)
129
+ expect(Rails.application.config.watchable_dirs).to eq({"/some/path/app/gold" => [:rb, :deface] })
134
130
  end
135
131
 
136
132
  end