erector-rails4 0.1.3 → 0.2.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -1
  3. data/.travis.yml +1 -1
  4. data/Appraisals +4 -1
  5. data/Guardfile +23 -0
  6. data/README.md +6 -1
  7. data/erector-rails4.gemspec +10 -3
  8. data/gemfiles/rails_3.gemfile +1 -0
  9. data/gemfiles/rails_4.0.gemfile +1 -0
  10. data/gemfiles/rails_4.1.gemfile +2 -1
  11. data/lib/erector-rails4.rb +1 -0
  12. data/lib/erector.rb +1 -4
  13. data/lib/erector/abstract_widget.rb +1 -12
  14. data/lib/erector/after_initialize.rb +7 -7
  15. data/lib/erector/caching.rb +35 -71
  16. data/lib/erector/element.rb +4 -4
  17. data/lib/erector/externals.rb +0 -8
  18. data/lib/erector/html_widget.rb +0 -11
  19. data/lib/erector/needs.rb +20 -9
  20. data/lib/erector/output.rb +2 -4
  21. data/lib/erector/promise.rb +4 -4
  22. data/lib/erector/rails.rb +6 -1
  23. data/lib/erector/rails/autoload_monkeypatch.rb +1 -1
  24. data/lib/erector/rails/railtie.rb +15 -8
  25. data/lib/erector/rails/template_handler.rb +2 -1
  26. data/lib/erector/text.rb +4 -8
  27. data/lib/erector/version.rb +1 -1
  28. data/lib/erector/widget.rb +2 -11
  29. data/lib/erector/xml_widget.rb +14 -18
  30. data/script/bootstrap +30 -0
  31. data/script/cibuild +3 -0
  32. data/script/performance +3 -0
  33. data/script/release +38 -0
  34. data/spec/dummy/app/views/test/_partial_with_rails_helpers.rb +7 -0
  35. data/spec/dummy/app/views/test/_user.rb +7 -0
  36. data/spec/dummy/app/views/test/_virtual_path_partial.rb +5 -0
  37. data/spec/dummy/app/views/test/erb_from_erector.html.rb +1 -1
  38. data/spec/dummy/app/views/test/erector_with_helpers_from_erb.html.erb +1 -0
  39. data/spec/dummy/app/views/test/{needs.html.rb → needs.rb} +0 -0
  40. data/spec/dummy/app/views/test/{needs_subclass.html.rb → needs_subclass.rb} +0 -0
  41. data/spec/dummy/app/views/test/render_partial.html.rb +1 -1
  42. data/spec/dummy/app/views/test/render_virtual_path.rb +7 -0
  43. data/spec/dummy/app/views/test/users.rb +9 -0
  44. data/spec/dummy/app/views/test_caching/_foos.rb +7 -0
  45. data/spec/dummy/app/views/test_caching/_partial.rb +9 -0
  46. data/spec/dummy/app/views/test_caching/cache_helper.rb +9 -0
  47. data/spec/dummy/app/views/test_caching/cache_helper_with_explicit_dependencies.rb +7 -0
  48. data/spec/dummy/app/views/test_caching/cache_helper_with_implicit_dependencies.rb +7 -0
  49. data/spec/dummy/app/views/test_caching/cache_helper_with_partial.rb +10 -0
  50. data/spec/dummy/app/views/test_caching/cache_helper_with_skip_digest.rb +9 -0
  51. data/spec/dummy/app/views/test_caching/cacheable_widget_with_dynamic_keys.rb +13 -0
  52. data/spec/dummy/app/views/test_caching/cacheable_widget_with_needs.rb +11 -0
  53. data/spec/dummy/app/views/test_caching/cacheable_widget_with_needs_keys.rb +11 -0
  54. data/spec/dummy/app/views/test_caching/cacheable_widget_with_skip_digest.rb +9 -0
  55. data/spec/dummy/app/views/test_caching/cacheable_widget_with_static_keys.rb +9 -0
  56. data/spec/dummy/config/application.rb +1 -1
  57. data/spec/dummy/spec/autoload_spec.rb +2 -2
  58. data/spec/dummy/spec/caching_spec.rb +180 -0
  59. data/spec/dummy/spec/form_builder_spec.rb +1 -1
  60. data/spec/dummy/spec/rails_helpers_spec.rb +21 -13
  61. data/spec/dummy/spec/rails_widget_spec.rb +1 -1
  62. data/spec/dummy/spec/render_spec.rb +23 -42
  63. data/spec/erector/dependency_spec.rb +0 -1
  64. data/spec/erector/html_spec.rb +4 -4
  65. data/spec/erector/indentation_spec.rb +2 -2
  66. data/spec/erector/needs_spec.rb +33 -0
  67. data/spec/erector/output_spec.rb +0 -2
  68. data/spec/erector/promise_spec.rb +2 -2
  69. data/spec/erector/widget_spec.rb +2 -2
  70. data/spec/performance/allocation_spec.rb +19 -0
  71. data/spec/performance/ruby_prof_spec.rb +23 -0
  72. data/spec/performance/widget_to_html_spec.rb +11 -5
  73. data/spec/spec_helper.rb +1 -10
  74. data/spec/support/capturing_output.rb +8 -0
  75. metadata +116 -17
  76. data/lib/erector/cache.rb +0 -41
  77. data/lib/erector/raw_string.rb +0 -12
  78. data/spec/dummy/spec/rails_spec_helper.rb +0 -10
  79. data/spec/erector/cache_spec.rb +0 -133
  80. data/spec/erector/caching_spec.rb +0 -202
@@ -0,0 +1,10 @@
1
+ class Views::TestCaching::CacheHelperWithPartial < Erector::Widget
2
+
3
+ def content
4
+ cache 'cache_helper_with_partial_key' do
5
+ text DateTime.current
6
+ render 'partial'
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,9 @@
1
+ class Views::TestCaching::CacheHelperWithSkipDigest < Erector::Widget
2
+
3
+ def content
4
+ cache 'cache_helper_with_skip_digest_key', skip_digest: true do
5
+ text DateTime.current
6
+ end
7
+ end
8
+
9
+ end
@@ -0,0 +1,13 @@
1
+ class Views::TestCaching::CacheableWidgetWithDynamicKeys < Erector::Widget
2
+
3
+ cacheable :current_user
4
+
5
+ def content
6
+ text DateTime.current
7
+ end
8
+
9
+ def current_user
10
+ 'the current user'
11
+ end
12
+
13
+ end
@@ -0,0 +1,11 @@
1
+ class Views::TestCaching::CacheableWidgetWithNeeds < Erector::Widget
2
+
3
+ needs :person, :food
4
+
5
+ cacheable
6
+
7
+ def content
8
+ text DateTime.current
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ class Views::TestCaching::CacheableWidgetWithNeedsKeys < Erector::Widget
2
+
3
+ needs :person, :food, beer: 'beer'
4
+
5
+ cacheable needs_keys: [:person, :beer]
6
+
7
+ def content
8
+ text DateTime.current
9
+ end
10
+
11
+ end
@@ -0,0 +1,9 @@
1
+ class Views::TestCaching::CacheableWidgetWithSkipDigest < Erector::Widget
2
+
3
+ cacheable skip_digest: true
4
+
5
+ def content
6
+ text DateTime.current
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ class Views::TestCaching::CacheableWidgetWithStaticKeys < Erector::Widget
2
+
3
+ cacheable 'v1'
4
+
5
+ def content
6
+ text DateTime.current
7
+ end
8
+
9
+ end
@@ -13,7 +13,7 @@ module Dummy
13
13
  # -- all .rb files in that directory are automatically loaded.
14
14
 
15
15
  # Custom directories with classes and modules you want to be autoloadable.
16
- config.autoload_paths += %W(#{config.root}/app)
16
+ # config.autoload_paths += %W(#{config.root}/app)
17
17
 
18
18
  config.cache_store = :memory_store
19
19
 
@@ -1,4 +1,4 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/rails_spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  describe 'Autoload' do
4
4
 
@@ -10,4 +10,4 @@ describe 'Autoload' do
10
10
  Views::Test::Erector.new
11
11
  end
12
12
 
13
- end
13
+ end
@@ -0,0 +1,180 @@
1
+ require 'ostruct'
2
+ require 'spec_helper'
3
+
4
+ describe 'Caching' do
5
+
6
+ next unless Gem::Version.new(::Rails.version) >= Gem::Version.new('4.0.0')
7
+
8
+ class TestCachingController < ActionController::Base
9
+ layout false
10
+
11
+ # Let exceptions propagate rather than generating the usual error page.
12
+ include ActionController::TestCase::RaiseActionExceptions
13
+
14
+ def cache_helper
15
+ end
16
+
17
+ def cache_helper_with_partial
18
+ end
19
+
20
+ def cache_helper_with_skip_digest
21
+ end
22
+
23
+ def cache_helper_with_implicit_dependencies
24
+ end
25
+
26
+ def cacheable_widget_with_needs
27
+ @person = 'person'
28
+ @food = 'food'
29
+ end
30
+
31
+ def cacheable_widget_with_needs_keys
32
+ @person = 'person'
33
+ @food = 'food'
34
+ end
35
+
36
+ def cacheable_widget_with_skip_digest
37
+ end
38
+
39
+ def cacheable_widget_with_static_keys
40
+ end
41
+
42
+ def cacheable_widget_with_dynamic_keys
43
+ end
44
+ end
45
+
46
+ def test_action(action)
47
+ @response = TestCachingController.action(action).call(Rack::MockRequest.env_for("/path"))[2]
48
+ @response.body
49
+ end
50
+
51
+ def digestor_for(template_name)
52
+ if Gem::Version.new(::Rails.version) > Gem::Version.new('4.0.0')
53
+ ActionView::Digestor.new(name: "test_caching/#{template_name}.rb", finder: ActionController::Base.new.lookup_context)
54
+ else
55
+ ActionView::Digestor.new("test_caching/#{template_name}", :rb, ActionController::Base.new.lookup_context)
56
+ end
57
+ end
58
+
59
+ context 'disabled in Rails config' do
60
+ before do
61
+ allow_any_instance_of(TestCachingController).to receive(:perform_caching).and_return(false)
62
+ end
63
+
64
+ it 'does not perform caching' do
65
+ expect(DateTime).to receive(:current).exactly(2).times
66
+ 2.times { test_action(:cache_helper) }
67
+ end
68
+ end
69
+
70
+ before(:each) do
71
+ ::Rails.cache.clear
72
+ end
73
+
74
+ describe 'helpers.cache' do
75
+ context 'for a template' do
76
+ it 'calculates the fragment' do
77
+ expect_any_instance_of(TestCachingController).to receive(:read_fragment).
78
+ with(['cache_helper_key', 'bb530bfa0e2512415cc491ae2cb67b31'], nil)
79
+
80
+ test_action(:cache_helper)
81
+ end
82
+
83
+ it 'caches properly' do
84
+ expect(DateTime).to receive(:current).exactly(1).times
85
+ 2.times { test_action(:cache_helper) }
86
+ end
87
+ end
88
+
89
+ context 'for a partial' do
90
+ it 'calculates the fragment' do
91
+ expect_any_instance_of(TestCachingController).to receive(:read_fragment).
92
+ with(['cache_helper_with_partial_key', 'd344d73b7967f342b19f502ed75bf787'], nil)
93
+
94
+ expect_any_instance_of(TestCachingController).to receive(:read_fragment).
95
+ with(['partial_key', '50a64015c65ef2b37558333733245988'], nil)
96
+
97
+ test_action(:cache_helper_with_partial)
98
+ end
99
+
100
+ it 'caches properly' do
101
+ expect(DateTime).to receive(:current).exactly(2).times
102
+ 2.times { test_action(:cache_helper_with_partial) }
103
+ end
104
+ end
105
+
106
+ it 'can skip the digest with skip_digest: true' do
107
+ expect_any_instance_of(TestCachingController).to receive(:read_fragment).
108
+ with('cache_helper_with_skip_digest_key', skip_digest: true)
109
+
110
+ test_action(:cache_helper_with_skip_digest)
111
+ end
112
+
113
+ it 'honors implicit dependencies' do
114
+ digestor = digestor_for(:cache_helper_with_implicit_dependencies)
115
+ expect(digestor.dependencies).to eq ['test_caching/foos']
116
+ end
117
+
118
+ it 'honors explicit dependencies' do
119
+ digestor = digestor_for(:cache_helper_with_explicit_dependencies)
120
+ expect(digestor.dependencies).to eq ['test_caching/foos']
121
+ end
122
+ end
123
+
124
+ describe 'Widget.cacheable' do
125
+ it 'sets as cacheable' do
126
+ expect(Views::TestCaching::CacheableWidgetWithNeeds.new(person: nil, food: nil)).to be_cacheable
127
+ end
128
+
129
+ context ':needs as cache key' do
130
+ it 'calculates the fragment key' do
131
+ expect_any_instance_of(ActionView::Base).to receive(:cache).
132
+ with(['person', 'food'], skip_digest: nil)
133
+
134
+ test_action(:cacheable_widget_with_needs)
135
+ end
136
+ end
137
+
138
+ it 'can select using the :needs_keys option' do
139
+ expect_any_instance_of(ActionView::Base).to receive(:cache).
140
+ with(['person', 'beer'], skip_digest: nil)
141
+
142
+ test_action(:cacheable_widget_with_needs_keys)
143
+ end
144
+
145
+ it 'can skip the digest with skip_digest: true' do
146
+ expect_any_instance_of(ActionView::Base).to receive(:cache).
147
+ with([], skip_digest: true)
148
+
149
+ test_action(:cacheable_widget_with_skip_digest)
150
+ end
151
+
152
+ it 'can add dynamic keys' do
153
+ expect_any_instance_of(ActionView::Base).to receive(:cache).
154
+ with(['the current user'], skip_digest: nil)
155
+
156
+ test_action(:cacheable_widget_with_dynamic_keys)
157
+ end
158
+
159
+ it 'can add static keys' do
160
+ expect_any_instance_of(ActionView::Base).to receive(:cache).
161
+ with(['v1'], skip_digest: nil)
162
+
163
+ test_action(:cacheable_widget_with_static_keys)
164
+ end
165
+
166
+ it 'caches appropriately' do
167
+ expect(DateTime).to receive(:current).exactly(1).times
168
+ 2.times { test_action(:cacheable_widget_with_static_keys) }
169
+ end
170
+
171
+ it 'does not cache when called without rails helpers' do
172
+ expect(DateTime).to receive(:current).exactly(2).times
173
+ 2.times do
174
+ Views::TestCaching::CacheableWidgetWithStaticKeys.new.to_html
175
+ end
176
+ end
177
+
178
+ end
179
+
180
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/rails_spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  describe Erector::Rails::FormBuilder do
4
4
  describe ".parent_builder_class" do
@@ -1,10 +1,10 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/rails_spec_helper")
1
+ require 'spec_helper'
2
2
  require 'simple_form'
3
3
 
4
4
  describe Erector::Rails do
5
5
  before do
6
6
  @controller = ApplicationController.new
7
- @controller.request = ActionController::TestRequest.new
7
+ @controller.request = ActionDispatch::TestRequest.new
8
8
 
9
9
  @view = ActionView::Base.new
10
10
  @view.controller = @controller
@@ -53,6 +53,14 @@ describe Erector::Rails do
53
53
  end
54
54
  end
55
55
 
56
+ describe 'from a partial' do
57
+ it 'still works' do
58
+ test_render do
59
+ widget Views::Test::PartialWithRailsHelpers.new
60
+ end.should match('<form')
61
+ end
62
+ end
63
+
56
64
  describe "#link_to" do
57
65
  it "renders a link" do
58
66
  test_render do
@@ -107,7 +115,7 @@ describe Erector::Rails do
107
115
  root :to => "rails_helpers_spec#index"
108
116
  end
109
117
  @app_controller = ApplicationController.new
110
- @app_controller.request = ActionController::TestRequest.new
118
+ @app_controller.request = ActionDispatch::TestRequest.new
111
119
  def app_render(&block)
112
120
  Erector::Rails.render(Erector.inline(&block), @app_controller.view_context)
113
121
  end
@@ -187,7 +195,7 @@ describe Erector::Rails do
187
195
  it "supports block syntax" do
188
196
  test_render do
189
197
  javascript_tag do
190
- text! "alert('All is good')"
198
+ rawtext "alert('All is good')"
191
199
  end
192
200
  end.should == %{<script#{@script_type_tag}>\n//<![CDATA[\nalert('All is good')\n//]]>\n</script>}
193
201
  end
@@ -256,14 +264,14 @@ describe Erector::Rails do
256
264
  end
257
265
  end
258
266
 
259
- # describe "#simple_form_for" do
260
- # it "instantiates a SimpleForm builder" do
261
- # test_render do
262
- # simple_form_for(:something, :url => "/test") do |form|
263
- # form.input :foobar
264
- # end
265
- # end.should =~ /foobar/
266
- # end
267
- # end
267
+ describe "#simple_form_for" do
268
+ it "instantiates a SimpleForm builder" do
269
+ test_render do
270
+ simple_form_for(:something, :url => "/test") do |form|
271
+ form.input :foobar
272
+ end
273
+ end.should =~ /foobar/
274
+ end
275
+ end
268
276
 
269
277
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/rails_spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  describe Erector::Rails do
4
4
  include Erector::Mixin
@@ -1,27 +1,10 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/rails_spec_helper")
1
+ require 'spec_helper'
2
2
 
3
3
  describe ActionController::Base do
4
4
  class TestController < ActionController::Base
5
5
  # Let exceptions propagate rather than generating the usual error page.
6
6
  include ActionController::TestCase::RaiseActionExceptions
7
7
 
8
- # We need this, because we reference Views::Test::Needs below, and it
9
- # doesn't auto-load otherwise.
10
- require 'views/test/needs.html.rb'
11
-
12
- # replicate deprecated use for rails <3.2
13
- if (Gem::Version.new(Rails.version) < Gem::Version.new('3.2.0') rescue false)
14
- def render(*args, &block)
15
- options = args.extract_options!
16
- if options[:template]
17
- handlers = options.delete(:handlers)
18
- format = '.html' unless options.delete(:bare)
19
- options[:template] += "#{format}.#{handlers.first}"
20
- end
21
- render(*(args << options), &block)
22
- end
23
- end
24
-
25
8
  def render_widget_class
26
9
  @foobar = "foobar"
27
10
  render :widget => TestWidget
@@ -49,16 +32,6 @@ describe ActionController::Base do
49
32
  render :widget => TestWidget, :content_method_name => :content_method
50
33
  end
51
34
 
52
- def render_with_cache_one
53
- @name = 'One'
54
- render :widget => CashWidget
55
- end
56
-
57
- def render_with_cache_two
58
- @name = 'Two'
59
- render :widget => CashWidget
60
- end
61
-
62
35
  def render_with_rails_options
63
36
  render :widget => TestWidget, :status => 500, :content_type => "application/json"
64
37
  end
@@ -139,6 +112,10 @@ describe ActionController::Base do
139
112
  render :template => 'test/erector_with_locals_from_erb', :handlers => [:erb]
140
113
  end
141
114
 
115
+ def render_erector_with_helpers_from_erb
116
+ render :template => 'test/erector_with_helpers_from_erb', :handlers => [:erb]
117
+ end
118
+
142
119
  def render_erector_with_locals_from_erb_defaulted
143
120
  @local_foo = "hihi"
144
121
  render :template => 'test/erector_with_locals_from_erb', :handlers => [:erb]
@@ -207,9 +184,17 @@ describe ActionController::Base do
207
184
  render :template => "test/render_with_widget_as_layout", :layout => "layouts/widget_as_layout"
208
185
  end
209
186
 
187
+ def render_with_needs_name_same_as_partial_name
188
+ render template: 'test/users', layout: false
189
+ end
190
+
210
191
  def render_with_widget_as_layout_using_content_for
211
192
  render :template => "test/render_with_widget_as_layout_using_content_for", :layout => "layouts/widget_as_layout"
212
193
  end
194
+
195
+ def render_virtual_path
196
+ render template: "test/render_virtual_path", layout: false
197
+ end
213
198
  end
214
199
 
215
200
  class TestWidget < Erector::Widget
@@ -239,15 +224,6 @@ describe ActionController::Base do
239
224
  end
240
225
  end
241
226
 
242
- class CashWidget < Erector::Widget
243
- needs :name
244
- cacheable 'v1'
245
-
246
- def content
247
- text @name
248
- end
249
- end
250
-
251
227
  def test_action(action)
252
228
  @response = TestController.action(action).call(Rack::MockRequest.env_for("/path"))[2]
253
229
  @response.body
@@ -324,6 +300,10 @@ describe ActionController::Base do
324
300
  test_action(:render_erector_with_locals_from_erb).should == "Partial, foo hihi, bar byebye"
325
301
  end
326
302
 
303
+ it "should render an ERB template which uses an erector widget partial with helpers" do
304
+ test_action(:render_erector_with_helpers_from_erb).should match '<form'
305
+ end
306
+
327
307
  it "should render an ERB template which uses an erector widget partial with a defaulted local" do
328
308
  test_action(:render_erector_with_locals_from_erb_defaulted).should == "Partial, foo hihi, bar 12345"
329
309
  end
@@ -384,11 +364,12 @@ describe ActionController::Base do
384
364
  test_action(:render_with_widget_as_layout_using_content_for).should == "TOPBEFOREDURINGAFTER"
385
365
  end
386
366
 
387
- it "should cache properly" do
388
- test_action(:render_with_cache_one).should == "One"
389
- test_action(:render_with_cache_one).should == "One"
390
- test_action(:render_with_cache_two).should == "Two"
391
- test_action(:render_with_cache_two).should == "Two"
367
+ it "allows for the same needs name as partial name" do
368
+ test_action(:render_with_needs_name_same_as_partial_name).should == "FooBar"
369
+ end
370
+
371
+ it "passes the correct virtual path" do
372
+ test_action(:render_virtual_path).should == "test/render_virtual_path.rb,test/_virtual_path_partial.rb"
392
373
  end
393
374
 
394
375
  end