erector-rails4 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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