view_models 2.0.0 → 2.0.1
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.
- data/lib/shared/lib/view_models/base.rb +1 -1
- data/spec/padrino/integration/integration_spec.rb +287 -0
- data/spec/padrino/lib/helpers/collection_spec.rb +30 -0
- data/spec/rails2/integration/integration_spec.rb +279 -0
- data/spec/rails2/lib/extensions/active_record_spec.rb +31 -0
- data/spec/rails2/lib/extensions/model_reader_spec.rb +91 -0
- data/spec/rails2/lib/helpers/collection_spec.rb +30 -0
- data/spec/rails2/lib/helpers/view_spec.rb +18 -0
- data/spec/rails2/lib/view_models/base_spec.rb +109 -0
- data/spec/rails2/lib/view_models/view_spec.rb +12 -0
- data/spec/shared/lib/helpers/collection_spec.rb +191 -0
- data/spec/shared/lib/helpers/mapping_spec.rb +72 -0
- metadata +47 -26
@@ -71,7 +71,7 @@ module ViewModels
|
|
71
71
|
# Just raises a fitting template error.
|
72
72
|
#
|
73
73
|
def raise_template_error_with message
|
74
|
-
raise MissingTemplateError.new
|
74
|
+
raise MissingTemplateError.new("No template #{message} found.")
|
75
75
|
end
|
76
76
|
# Check if the view lookup inheritance chain has ended.
|
77
77
|
#
|
@@ -0,0 +1,287 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../spec_helper')
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'models/subclass')
|
4
|
+
require File.join(File.dirname(__FILE__), 'models/sub_subclass')
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), 'view_models/project')
|
7
|
+
require File.join(File.dirname(__FILE__), 'view_models/subclass')
|
8
|
+
require File.join(File.dirname(__FILE__), 'view_models/sub_subclass')
|
9
|
+
require File.join(File.dirname(__FILE__), 'view_models/module_for_rendering')
|
10
|
+
|
11
|
+
class TestApp < Padrino::Application
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
TestApp.helpers ViewModels::Helpers::Mapping
|
16
|
+
|
17
|
+
describe 'Integration' do
|
18
|
+
|
19
|
+
before(:each) do
|
20
|
+
begin
|
21
|
+
# @controller = TestController.new
|
22
|
+
# @controller.class.view_paths = ['rails/spec/integration/views']
|
23
|
+
#
|
24
|
+
#
|
25
|
+
# @request = ActionController::TestRequest.new
|
26
|
+
# @response = ActionController::TestResponse.new
|
27
|
+
# @controller.request = @request
|
28
|
+
# @controller.response = @response
|
29
|
+
#
|
30
|
+
# # TODO Make separate contexts, one where the controller has rendered, one where it has not.
|
31
|
+
# #
|
32
|
+
# # Let the Controller generate a view instance.
|
33
|
+
# #
|
34
|
+
# # @controller.process @request, @response
|
35
|
+
#
|
36
|
+
# @view = ActionView::Base.new @controller.class.view_paths, {}, @controller
|
37
|
+
|
38
|
+
@app = stub :app
|
39
|
+
TestApp.new(@app) do |some_app|
|
40
|
+
@context = some_app
|
41
|
+
end
|
42
|
+
|
43
|
+
@logger = stub :logger, :null_object => true
|
44
|
+
Thread.current[:padrino_logger] = @logger
|
45
|
+
|
46
|
+
@model = SubSubclass.new
|
47
|
+
@model.id = :some_id
|
48
|
+
@view_model = ViewModels::SubSubclass.new @model, @context
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
before(:all) { puts "\n#{self.send(:description_args)[0]}:" }
|
53
|
+
|
54
|
+
# context 'experimental inclusion of module in render hierarchy' do
|
55
|
+
# before(:each) do
|
56
|
+
# ViewModels::Base.send :include, ModulesInRenderHierarchy
|
57
|
+
# @view_model.class.send :include, ModuleForRendering
|
58
|
+
# end
|
59
|
+
# describe 'render_as' do
|
60
|
+
# it 'should description' do
|
61
|
+
# @view_model.render_as(:not_found_in_sub_subclass_but_in_module).should == '_not_found_in_sub_subclass_but_in_module.erb'
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
|
66
|
+
# TODO Not ActiveRecord Extensions.
|
67
|
+
#
|
68
|
+
describe 'ActiveRecord Extensions' do
|
69
|
+
before(:each) do
|
70
|
+
@view_model.extend ViewModels::Extensions::ActiveRecord
|
71
|
+
end
|
72
|
+
it 'should delegate the id' do
|
73
|
+
@view_model.id.should == :some_id
|
74
|
+
end
|
75
|
+
# it 'should delegate the id' do
|
76
|
+
# @view_model.dom_id.should == 'sub_subclass_some_id'
|
77
|
+
# end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'view_model_for' do
|
81
|
+
context 'view model' do
|
82
|
+
it 'should be available' do
|
83
|
+
lambda { @view_model.view_model_for @model }.should_not raise_error
|
84
|
+
end
|
85
|
+
it 'should return the right one' do
|
86
|
+
@view_model.view_model_for(@model).should be_kind_of(ViewModels::SubSubclass)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
describe 'view_model_class_for' do
|
91
|
+
context 'view model' do
|
92
|
+
it 'should be available' do
|
93
|
+
lambda { @view_model.view_model_class_for @model }.should_not raise_error
|
94
|
+
end
|
95
|
+
it 'should return the right class' do
|
96
|
+
@view_model.view_model_class_for(@model).should == ViewModels::SubSubclass
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# describe 'capture in view model method' do
|
102
|
+
# context 'template' do
|
103
|
+
# it 'should capture the content of the block' do
|
104
|
+
# @view_model.render_as(:capture_in_template).should == 'Capturing: A Pirate!'
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
# context 'in view model' do
|
108
|
+
# it 'should capture the content of the block' do
|
109
|
+
# @view_model.render_as(:capture_in_view_model).should == 'Capturing: A Pirate!'
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
|
114
|
+
# TODO Write similar.
|
115
|
+
# describe 'app context' do
|
116
|
+
# it 'should work' do
|
117
|
+
# controller = ActionController::Base.new
|
118
|
+
#
|
119
|
+
# lambda {
|
120
|
+
# ViewModels::SubSubclass.new @model, controller
|
121
|
+
# }.should_not raise_error
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
|
125
|
+
# TODO Write anew.
|
126
|
+
# describe 'view_model_for inclusion in view' do
|
127
|
+
# it 'should be included' do
|
128
|
+
# view = ActionView::Base.new
|
129
|
+
#
|
130
|
+
# lambda {
|
131
|
+
# view.view_model_for @model
|
132
|
+
# }.should_not raise_error
|
133
|
+
# end
|
134
|
+
# end
|
135
|
+
|
136
|
+
describe 'collection rendering' do
|
137
|
+
context 'default format' do
|
138
|
+
it 'should render a html list' do
|
139
|
+
@view_model.render_as(:list_example).should == "\n\n<ol class=\"collection\"><li>_list_item.html.erb</li><li>_list_item.html.erb</li></ol>"
|
140
|
+
end
|
141
|
+
it 'should render a html collection' do
|
142
|
+
@view_model.render_as(:collection_example).should == "\n\n<ul class=\"collection\"><li>_collection_item.html.erb</li><li>_collection_item.html.erb</li></ul>"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
context 'format html' do
|
146
|
+
it 'should render a html list' do
|
147
|
+
@view_model.render_as(:list_example, :format => :html).should == "\n\n<ol class=\"collection\"><li>_list_item.html.erb</li><li>_list_item.html.erb</li></ol>"
|
148
|
+
end
|
149
|
+
it 'should render a html collection' do
|
150
|
+
@view_model.render_as(:collection_example, :format => :html).should == "\n\n<ul class=\"collection\"><li>_collection_item.html.erb</li><li>_collection_item.html.erb</li></ul>"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
context 'format text' do
|
154
|
+
it 'should render a text list' do
|
155
|
+
@view_model.render_as(:list_example, :format => :text).should == "\n\n_list_item.text.erb\\n_list_item.text.erb"
|
156
|
+
end
|
157
|
+
it 'should render a text collection' do
|
158
|
+
@view_model.render_as(:collection_example, :format => :text).should == "\n\n_collection_item.text.erb_collection_item.text.erb"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'model attributes' do
|
164
|
+
it 'should pass through unfiltered attributes' do
|
165
|
+
@view_model.some_untouched_attribute.should == :some_value
|
166
|
+
end
|
167
|
+
it 'should filter some attributes' do
|
168
|
+
@view_model.some_filtered_attribute.should == '%3Cscript%3Efilter+me%3C%2Fscript%3E'
|
169
|
+
end
|
170
|
+
it 'should filter some attributes multiple times' do
|
171
|
+
@view_model.some_doubly_doubled_attribute.should == 'blahblahblahblah'
|
172
|
+
end
|
173
|
+
it 'should filter some attributes multiple times correctly' do
|
174
|
+
@view_model.some_mangled_attribute.should == 'DCBDCB'
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe 'app_method' do
|
179
|
+
it 'should delegate to the context' do
|
180
|
+
@view_model.logger.should == @logger
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "render_template" do
|
185
|
+
it "should render the right template" do
|
186
|
+
@view_model.render_template(:show).should == 'show.html.erb'
|
187
|
+
end
|
188
|
+
it "should render the right template with format" do
|
189
|
+
@view_model.render_template(:show, :format => :text).should == 'show.text.erb'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'render_as' do
|
194
|
+
describe 'render_the alias' do
|
195
|
+
it 'should also render' do
|
196
|
+
@view_model.render_the(:part_that_is_dependent_on_the_view_model).should == '_part_that_is_dependent_on_the_view_model.erb'
|
197
|
+
end
|
198
|
+
end
|
199
|
+
describe "explicit partial rendering" do
|
200
|
+
it "should render the right partial" do
|
201
|
+
# If one wants explicit template rendering, he needs to work more.
|
202
|
+
# Let's be opinionated here :)
|
203
|
+
#
|
204
|
+
@view_model.render_as(:partial => 'view_models/sub_subclass/inner', :format => :nesting).should == '_inner.nesting.erb'
|
205
|
+
end
|
206
|
+
end
|
207
|
+
describe "nesting" do
|
208
|
+
it "should render the right nested template, with an explicitly defined format (see template)" do
|
209
|
+
@view_model.render_as(:outer, :format => :explicit).should == '_inner.also_explicit.erb'
|
210
|
+
end
|
211
|
+
it "should render the right nested template, respecting the already defined format" do
|
212
|
+
@view_model.render_as(:outer, :format => :nesting).should == '_inner.nesting.erb'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
describe 'template inheritance' do
|
216
|
+
it 'should raise ViewModels::MissingTemplateError if template is not found' do
|
217
|
+
lambda { @view_model.render_as(:this_template_does_not_exist_at_allllll) }.should raise_error(ViewModels::MissingTemplateError, "No template '_this_template_does_not_exist_at_allllll' with default format found.")
|
218
|
+
end
|
219
|
+
it 'should raise ViewModels::MissingTemplateError if template is not found, with specific path' do
|
220
|
+
lambda { @view_model.render_as(:partial => 'view_models/sub_subclass/this_template_does_not_exist_at_allllll') }.should raise_error(ViewModels::MissingTemplateError, "No template 'view_models/sub_subclass/_this_template_does_not_exist_at_allllll' with default format found.")
|
221
|
+
end
|
222
|
+
it 'should raise ViewModels::MissingTemplateError if template is not found, with format' do
|
223
|
+
lambda { @view_model.render_as(:this_template_does_not_exist_at_allllll, :format => :gaga) }.should raise_error(ViewModels::MissingTemplateError, "No template '_this_template_does_not_exist_at_allllll' with format gaga found.")
|
224
|
+
end
|
225
|
+
it "should use its own template" do
|
226
|
+
@view_model.render_as(:exists).should == '_exists.html.erb' # The default
|
227
|
+
end
|
228
|
+
it "should use the subclass' template" do
|
229
|
+
@view_model.render_as(:no_sub_subclass).should == '_no_sub_subclass.erb'
|
230
|
+
end
|
231
|
+
end
|
232
|
+
describe 'format' do
|
233
|
+
it 'should render html' do
|
234
|
+
@view_model.render_as(:exists, :format => nil).should == '_exists.html.erb' # the default
|
235
|
+
end
|
236
|
+
it 'should render erb' do
|
237
|
+
@view_model.render_as(:exists, :format => '').should == '_exists.erb'
|
238
|
+
end
|
239
|
+
it 'should render text' do
|
240
|
+
@view_model.render_as(:exists, :format => :text).should == '_exists.text.erb'
|
241
|
+
end
|
242
|
+
it 'should render html' do
|
243
|
+
@view_model.render_as(:exists, :format => :html).should == '_exists.html.erb'
|
244
|
+
end
|
245
|
+
end
|
246
|
+
describe 'locals' do
|
247
|
+
it 'should render html' do
|
248
|
+
@view_model.render_as(:exists, :locals => { :local_name => :some_local }).should == '_exists.html.erb with some_local'
|
249
|
+
end
|
250
|
+
it 'should render html' do
|
251
|
+
@view_model.render_as(:exists, :format => nil, :locals => { :local_name => :some_local }).should == '_exists.html.erb with some_local'
|
252
|
+
end
|
253
|
+
it 'should render text' do
|
254
|
+
@view_model.render_as(:exists, :format => '', :locals => { :local_name => :some_local }).should == '_exists.erb with some_local'
|
255
|
+
end
|
256
|
+
it 'should render text' do
|
257
|
+
@view_model.render_as(:exists, :format => :text, :locals => { :local_name => :some_local }).should == '_exists.text.erb with some_local'
|
258
|
+
end
|
259
|
+
it 'should render html' do
|
260
|
+
@view_model.render_as(:exists, :format => :html, :locals => { :local_name => :some_local }).should == '_exists.html.erb with some_local'
|
261
|
+
end
|
262
|
+
end
|
263
|
+
describe 'memoizing' do
|
264
|
+
it 'should memoize and not generate always a new path' do
|
265
|
+
@view_model.class.should_receive(:generate_template_path_from).once.and_return "view_models/sub_subclass/_not_found_in_sub_subclass"
|
266
|
+
|
267
|
+
@view_model.render_as :not_found_in_sub_subclass
|
268
|
+
@view_model.render_as :not_found_in_sub_subclass
|
269
|
+
@view_model.render_as :not_found_in_sub_subclass
|
270
|
+
@view_model.render_as :not_found_in_sub_subclass
|
271
|
+
@view_model.render_as :not_found_in_sub_subclass
|
272
|
+
end
|
273
|
+
it 'should render the right one' do
|
274
|
+
@view_model.render_as :exists_in_both
|
275
|
+
@view_model.render_as(:exists_in_both).should == 'in sub subclass'
|
276
|
+
|
277
|
+
other_view_model = ViewModels::Subclass.new Subclass.new, @context
|
278
|
+
other_view_model.render_as :exists_in_both
|
279
|
+
other_view_model.render_as(:exists_in_both).should == 'in subclass'
|
280
|
+
|
281
|
+
@view_model.render_as :exists_in_both
|
282
|
+
@view_model.render_as(:exists_in_both).should == 'in sub subclass'
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Helpers::Mapping::Collection do
|
4
|
+
include ViewModels::Helpers::Mapping
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@collection = stub :collection
|
8
|
+
@context = stub :context
|
9
|
+
@collection_view_model = ViewModels::Helpers::Mapping::Collection.new @collection, @context
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "render_partial" do
|
13
|
+
it "should call instance eval on the context" do
|
14
|
+
@context.should_receive(:instance_eval).once
|
15
|
+
|
16
|
+
@collection_view_model.send :render_partial, :some_name, :some_params
|
17
|
+
end
|
18
|
+
it "should render the partial in the 'context' context" do
|
19
|
+
@context.should_receive(:render).once
|
20
|
+
|
21
|
+
@collection_view_model.send :render_partial, :some_name, :some_params
|
22
|
+
end
|
23
|
+
it "should call render partial on context with the passed through parameters" do
|
24
|
+
@context.should_receive(:render).once.with('view_models/collection/_some_name', :locals => { :a => :b })
|
25
|
+
|
26
|
+
@collection_view_model.send :render_partial, :some_name, { :a => :b }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
this = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require File.join(this, '/../spec_helper')
|
4
|
+
|
5
|
+
require File.join(this, 'models/subclass')
|
6
|
+
require File.join(this, 'models/sub_subclass')
|
7
|
+
|
8
|
+
require File.join(this, 'view_models/project')
|
9
|
+
require File.join(this, 'view_models/subclass')
|
10
|
+
require File.join(this, 'view_models/sub_subclass')
|
11
|
+
require File.join(this, 'view_models/module_for_rendering')
|
12
|
+
|
13
|
+
require 'action_controller'
|
14
|
+
require 'action_controller/test_process'
|
15
|
+
|
16
|
+
class TestController < ActionController::Base; end
|
17
|
+
|
18
|
+
ActionView::Base.send :include, ViewModels::Helpers::Mapping
|
19
|
+
|
20
|
+
describe 'Integration' do
|
21
|
+
|
22
|
+
before(:each) do
|
23
|
+
begin
|
24
|
+
@controller = TestController.new
|
25
|
+
@controller.class.view_paths = ['spec/rails2/integration/views']
|
26
|
+
|
27
|
+
@logger = stub :logger, :null_object => true
|
28
|
+
@controller.logger = @logger
|
29
|
+
|
30
|
+
@request = ActionController::TestRequest.new
|
31
|
+
@response = ActionController::TestResponse.new
|
32
|
+
@controller.request = @request
|
33
|
+
@controller.response = @response
|
34
|
+
|
35
|
+
# TODO Make separate contexts, one where the controller has rendered, one where it has not.
|
36
|
+
#
|
37
|
+
# Let the Controller generate a view instance.
|
38
|
+
#
|
39
|
+
# @controller.process @request, @response
|
40
|
+
|
41
|
+
@view = ActionView::Base.new @controller.class.view_paths, {}, @controller
|
42
|
+
@model = SubSubclass.new
|
43
|
+
@model.id = :some_id
|
44
|
+
@view_model = ViewModels::SubSubclass.new @model, @view
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
before(:all) { puts "\n#{self.send(:description_args)[0]}:" }
|
49
|
+
|
50
|
+
# context 'experimental inclusion of module in render hierarchy' do
|
51
|
+
# before(:each) do
|
52
|
+
# ViewModels::Base.send :include, ModulesInRenderHierarchy
|
53
|
+
# @view_model.class.send :include, ModuleForRendering
|
54
|
+
# end
|
55
|
+
# describe 'render_as' do
|
56
|
+
# it 'should description' do
|
57
|
+
# @view_model.render_as(:not_found_in_sub_subclass_but_in_module).should == '_not_found_in_sub_subclass_but_in_module.erb'
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
|
62
|
+
describe 'ActiveRecord Extensions' do
|
63
|
+
before(:each) do
|
64
|
+
@view_model.extend ViewModels::Extensions::ActiveRecord
|
65
|
+
end
|
66
|
+
it 'should delegate the id' do
|
67
|
+
@view_model.id.should == :some_id
|
68
|
+
end
|
69
|
+
it 'should delegate the id' do
|
70
|
+
@view_model.dom_id.should == 'sub_subclass_some_id'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'view_model_for' do
|
75
|
+
context 'view model' do
|
76
|
+
it 'should be available' do
|
77
|
+
lambda { @view_model.view_model_for @model }.should_not raise_error
|
78
|
+
end
|
79
|
+
it 'should return the right one' do
|
80
|
+
@view_model.view_model_for(@model).should be_kind_of(ViewModels::SubSubclass)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
describe 'view_model_class_for' do
|
85
|
+
context 'view model' do
|
86
|
+
it 'should be available' do
|
87
|
+
lambda { @view_model.view_model_class_for @model }.should_not raise_error
|
88
|
+
end
|
89
|
+
it 'should return the right class' do
|
90
|
+
@view_model.view_model_class_for(@model).should == ViewModels::SubSubclass
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'capture in view model method' do
|
96
|
+
context 'template' do
|
97
|
+
it 'should capture the content of the block' do
|
98
|
+
@view_model.render_as(:capture_in_template).should == 'Capturing: A Pirate!'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
context 'in view model' do
|
102
|
+
it 'should capture the content of the block' do
|
103
|
+
@view_model.render_as(:capture_in_view_model).should == 'Capturing: A Pirate!'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'controller context' do
|
109
|
+
it 'should work' do
|
110
|
+
controller = ActionController::Base.new
|
111
|
+
|
112
|
+
lambda {
|
113
|
+
ViewModels::SubSubclass.new @model, controller
|
114
|
+
}.should_not raise_error
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'view_model_for inclusion in view' do
|
119
|
+
it 'should be included' do
|
120
|
+
view = ActionView::Base.new
|
121
|
+
|
122
|
+
lambda {
|
123
|
+
view.view_model_for @model
|
124
|
+
}.should_not raise_error
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'collection rendering' do
|
129
|
+
context 'default format' do
|
130
|
+
it 'should render a html list' do
|
131
|
+
@view_model.render_as(:list_example).should == "<ol class=\"collection\"><li>_list_item.html.erb</li><li>_list_item.html.erb</li></ol>"
|
132
|
+
end
|
133
|
+
it 'should render a html collection' do
|
134
|
+
@view_model.render_as(:collection_example).should == "<ul class=\"collection\"><li>_collection_item.html.erb</li><li>_collection_item.html.erb</li></ul>"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
context 'format html' do
|
138
|
+
it 'should render a html list' do
|
139
|
+
@view_model.render_as(:list_example, :format => :html).should == "<ol class=\"collection\"><li>_list_item.html.erb</li><li>_list_item.html.erb</li></ol>"
|
140
|
+
end
|
141
|
+
it 'should render a html collection' do
|
142
|
+
@view_model.render_as(:collection_example, :format => :html).should == "<ul class=\"collection\"><li>_collection_item.html.erb</li><li>_collection_item.html.erb</li></ul>"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
context 'format text' do
|
146
|
+
it 'should render a text list' do
|
147
|
+
@view_model.render_as(:list_example, :format => :text).should == '_list_item.text.erb\n_list_item.text.erb'
|
148
|
+
end
|
149
|
+
it 'should render a text collection' do
|
150
|
+
@view_model.render_as(:collection_example, :format => :text).should == '_collection_item.text.erb_collection_item.text.erb'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'model attributes' do
|
156
|
+
it 'should pass through unfiltered attributes' do
|
157
|
+
@view_model.some_untouched_attribute.should == :some_value
|
158
|
+
end
|
159
|
+
it 'should filter some attributes' do
|
160
|
+
@view_model.some_filtered_attribute.should == '%3Cscript%3Efilter+me%3C%2Fscript%3E'
|
161
|
+
end
|
162
|
+
it 'should filter some attributes multiple times' do
|
163
|
+
@view_model.some_doubly_doubled_attribute.should == 'blahblahblahblah'
|
164
|
+
end
|
165
|
+
it 'should filter some attributes multiple times correctly' do
|
166
|
+
@view_model.some_mangled_attribute.should == 'DCBDCB'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe 'controller_method' do
|
171
|
+
it 'should delegate to the context' do
|
172
|
+
@view_model.logger.should == @logger
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "render_template" do
|
177
|
+
it "should render the right template" do
|
178
|
+
@view_model.render_template(:show).should == 'show.html.erb'
|
179
|
+
end
|
180
|
+
it "should render the right template with format" do
|
181
|
+
@view_model.render_template(:show, :format => :text).should == 'show.text.erb'
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe 'render_as' do
|
186
|
+
describe 'render_the alias' do
|
187
|
+
it 'should also render' do
|
188
|
+
@view_model.render_the(:part_that_is_dependent_on_the_view_model).should == '_part_that_is_dependent_on_the_view_model.erb'
|
189
|
+
end
|
190
|
+
end
|
191
|
+
describe "explicit partial rendering" do
|
192
|
+
it "should render the right partial" do
|
193
|
+
# If one wants explicit template rendering, he needs to work more.
|
194
|
+
# Let's be opinionated here :)
|
195
|
+
#
|
196
|
+
@view_model.render_as(:partial => 'view_models/sub_subclass/inner', :format => :nesting).should == '_inner.nesting.erb'
|
197
|
+
end
|
198
|
+
end
|
199
|
+
describe "nesting" do
|
200
|
+
it "should render the right nested template, with an explicitly defined format (see template)" do
|
201
|
+
@view_model.render_as(:outer, :format => :explicit).should == '_inner.also_explicit.erb'
|
202
|
+
end
|
203
|
+
it "should render the right nested template, respecting the already defined format" do
|
204
|
+
@view_model.render_as(:outer, :format => :nesting).should == '_inner.nesting.erb'
|
205
|
+
end
|
206
|
+
end
|
207
|
+
describe 'template inheritance' do
|
208
|
+
it 'should raise ViewModels::MissingTemplateError if template is not found' do
|
209
|
+
lambda { @view_model.render_as(:this_template_does_not_exist_at_allllll) }.should raise_error(ViewModels::MissingTemplateError, "No template '_this_template_does_not_exist_at_allllll' with default format found.")
|
210
|
+
end
|
211
|
+
it 'should raise ViewModels::MissingTemplateError if template is not found, with specific path' do
|
212
|
+
lambda { @view_model.render_as(:partial => 'view_models/sub_subclass/this_template_does_not_exist_at_allllll') }.should raise_error(ViewModels::MissingTemplateError, "No template 'view_models/sub_subclass/_this_template_does_not_exist_at_allllll' with default format found.")
|
213
|
+
end
|
214
|
+
it 'should raise ViewModels::MissingTemplateError if template is not found, with format' do
|
215
|
+
lambda { @view_model.render_as(:this_template_does_not_exist_at_allllll, :format => :gaga) }.should raise_error(ViewModels::MissingTemplateError, "No template '_this_template_does_not_exist_at_allllll' with format gaga found.")
|
216
|
+
end
|
217
|
+
it "should use its own template" do
|
218
|
+
@view_model.render_as(:exists).should == '_exists.html.erb' # The default
|
219
|
+
end
|
220
|
+
it "should use the subclass' template" do
|
221
|
+
@view_model.render_as(:no_sub_subclass).should == '_no_sub_subclass.erb'
|
222
|
+
end
|
223
|
+
end
|
224
|
+
describe 'format' do
|
225
|
+
it 'should render html' do
|
226
|
+
@view_model.render_as(:exists, :format => nil).should == '_exists.html.erb' # the default
|
227
|
+
end
|
228
|
+
it 'should render erb' do
|
229
|
+
@view_model.render_as(:exists, :format => '').should == '_exists.erb'
|
230
|
+
end
|
231
|
+
it 'should render text' do
|
232
|
+
@view_model.render_as(:exists, :format => :text).should == '_exists.text.erb'
|
233
|
+
end
|
234
|
+
it 'should render html' do
|
235
|
+
@view_model.render_as(:exists, :format => :html).should == '_exists.html.erb'
|
236
|
+
end
|
237
|
+
end
|
238
|
+
describe 'locals' do
|
239
|
+
it 'should render html' do
|
240
|
+
@view_model.render_as(:exists, :locals => { :local_name => :some_local }).should == '_exists.html.erb with some_local'
|
241
|
+
end
|
242
|
+
it 'should render html' do
|
243
|
+
@view_model.render_as(:exists, :format => nil, :locals => { :local_name => :some_local }).should == '_exists.html.erb with some_local'
|
244
|
+
end
|
245
|
+
it 'should render text' do
|
246
|
+
@view_model.render_as(:exists, :format => '', :locals => { :local_name => :some_local }).should == '_exists.erb with some_local'
|
247
|
+
end
|
248
|
+
it 'should render text' do
|
249
|
+
@view_model.render_as(:exists, :format => :text, :locals => { :local_name => :some_local }).should == '_exists.text.erb with some_local'
|
250
|
+
end
|
251
|
+
it 'should render html' do
|
252
|
+
@view_model.render_as(:exists, :format => :html, :locals => { :local_name => :some_local }).should == '_exists.html.erb with some_local'
|
253
|
+
end
|
254
|
+
end
|
255
|
+
describe 'memoizing' do
|
256
|
+
it 'should memoize and not generate always a new path' do
|
257
|
+
@view_model.class.should_receive(:generate_template_path_from).once.and_return "view_models/sub_subclass/_not_found_in_sub_subclass"
|
258
|
+
|
259
|
+
@view_model.render_as :not_found_in_sub_subclass
|
260
|
+
@view_model.render_as :not_found_in_sub_subclass
|
261
|
+
@view_model.render_as :not_found_in_sub_subclass
|
262
|
+
@view_model.render_as :not_found_in_sub_subclass
|
263
|
+
@view_model.render_as :not_found_in_sub_subclass
|
264
|
+
end
|
265
|
+
it 'should render the right one' do
|
266
|
+
@view_model.render_as :exists_in_both
|
267
|
+
@view_model.render_as(:exists_in_both).should == 'in sub subclass'
|
268
|
+
|
269
|
+
other_view_model = ViewModels::Subclass.new Subclass.new, @view
|
270
|
+
other_view_model.render_as :exists_in_both
|
271
|
+
other_view_model.render_as(:exists_in_both).should == 'in subclass'
|
272
|
+
|
273
|
+
@view_model.render_as :exists_in_both
|
274
|
+
@view_model.render_as(:exists_in_both).should == 'in sub subclass'
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Extensions::ActiveRecord do
|
4
|
+
|
5
|
+
describe "to_param" do
|
6
|
+
before(:each) do
|
7
|
+
@model = stub :model
|
8
|
+
@view_model = ViewModels::Base.new @model, nil
|
9
|
+
@view_model.extend ViewModels::Extensions::ActiveRecord
|
10
|
+
end
|
11
|
+
it "should delegate to_param to the model" do
|
12
|
+
@model.should_receive(:to_param).once
|
13
|
+
|
14
|
+
@view_model.to_param
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should delegate id to the model" do
|
18
|
+
@model.should_receive(:id).once
|
19
|
+
|
20
|
+
@view_model.id
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should delegate dom_id to ActionController::RecordIdentifier" do
|
24
|
+
ActionController::RecordIdentifier.should_receive(:dom_id).once
|
25
|
+
|
26
|
+
@view_model.dom_id
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Extensions::ModelReader do
|
4
|
+
|
5
|
+
class ModelReaderModel < Struct.new(:some_model_value); end
|
6
|
+
|
7
|
+
describe ".model_reader" do
|
8
|
+
before(:each) do
|
9
|
+
@model = ModelReaderModel.new
|
10
|
+
@view_model = ViewModels::Base.new(@model, nil)
|
11
|
+
class << @view_model
|
12
|
+
def a(s); s << 'a' end
|
13
|
+
def b(s); s << 'b' end
|
14
|
+
end
|
15
|
+
@model.some_model_value = 's'
|
16
|
+
end
|
17
|
+
it "should call filters in a given pattern" do
|
18
|
+
@view_model.class.model_reader :some_model_value, :filter_through => [:a, :b, :a, :a]
|
19
|
+
|
20
|
+
@view_model.some_model_value.should == 'sabaa'
|
21
|
+
end
|
22
|
+
it "should pass through the model value if no filters are installed" do
|
23
|
+
@view_model.class.model_reader :some_model_value
|
24
|
+
|
25
|
+
@view_model.some_model_value.should == 's'
|
26
|
+
end
|
27
|
+
it "should call filters in a given pattern" do
|
28
|
+
@view_model.class.model_reader [:some_model_value], :filter_through => [:a, :b, :a, :a]
|
29
|
+
|
30
|
+
@view_model.some_model_value.should == 'sabaa'
|
31
|
+
end
|
32
|
+
it "should handle a single filter" do
|
33
|
+
@view_model.class.model_reader :some_model_value, :filter_through => :a
|
34
|
+
|
35
|
+
lambda { @view_model.some_model_value }.should_not raise_error
|
36
|
+
end
|
37
|
+
it "should handle an array of readers" do
|
38
|
+
@view_model.class.model_reader [:some_model_value, :some_other_model_value], :filter_through => :a
|
39
|
+
|
40
|
+
lambda { @view_model.some_model_value }.should_not raise_error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'FilteredDelegationInstaller' do
|
45
|
+
before(:each) do
|
46
|
+
@model = ModelReaderModel.new
|
47
|
+
end
|
48
|
+
context 'with filters' do
|
49
|
+
before(:each) do
|
50
|
+
@options = ViewModels::Extensions::ModelReader::Options.new :some_attribute_name, :filter_through => [:filter1, :filter2]
|
51
|
+
@installer = ViewModels::Extensions::ModelReader::FilteredDelegationInstaller.new @model, @options
|
52
|
+
end
|
53
|
+
it 'should have a correct filter definition' do
|
54
|
+
@installer.reader_definition_for(:some_attribute).should == 'def some_attribute; filter2(filter1(model.some_attribute)); end'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
context 'without filters' do
|
58
|
+
before(:each) do
|
59
|
+
@options = ViewModels::Extensions::ModelReader::Options.new :some_attribute_name
|
60
|
+
@installer = ViewModels::Extensions::ModelReader::FilteredDelegationInstaller.new @model, @options
|
61
|
+
end
|
62
|
+
it 'should have a correct filter definition' do
|
63
|
+
@installer.reader_definition_for(:some_attribute).should == 'def some_attribute; model.some_attribute; end'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'Options' do
|
69
|
+
context 'without filters' do
|
70
|
+
before(:each) do
|
71
|
+
@options = ViewModels::Extensions::ModelReader::Options.new :some_attribute_name
|
72
|
+
end
|
73
|
+
describe 'split' do
|
74
|
+
it 'should return the right values' do
|
75
|
+
@options.to_a.should == [[:some_attribute_name], []]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
context 'with filters' do
|
80
|
+
before(:each) do
|
81
|
+
@options = ViewModels::Extensions::ModelReader::Options.new :some_attribute_name, :filter_through => [:filter1, :filter2]
|
82
|
+
end
|
83
|
+
describe 'split' do
|
84
|
+
it 'should return the right values, with flipped options' do
|
85
|
+
@options.to_a.should == [[:some_attribute_name], [:filter2, :filter1]]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Helpers::Mapping::Collection do
|
4
|
+
include ViewModels::Helpers::Mapping
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@collection = stub :collection
|
8
|
+
@context = stub :context
|
9
|
+
@collection_view_model = ViewModels::Helpers::Mapping::Collection.new @collection, @context
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "render_partial" do
|
13
|
+
it "should call instance eval on the context" do
|
14
|
+
@context.should_receive(:instance_eval).once
|
15
|
+
|
16
|
+
@collection_view_model.send :render_partial, :some_name, :some_params
|
17
|
+
end
|
18
|
+
it "should render the partial in the 'context' context" do
|
19
|
+
@context.should_receive(:render).once
|
20
|
+
|
21
|
+
@collection_view_model.send :render_partial, :some_name, :some_params
|
22
|
+
end
|
23
|
+
it "should call render partial on context with the passed through parameters" do
|
24
|
+
@context.should_receive(:render).once.with(:partial => 'view_models/collection/some_name', :locals => { :a => :b })
|
25
|
+
|
26
|
+
@collection_view_model.send :render_partial, :some_name, { :a => :b }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Helpers::View do
|
4
|
+
|
5
|
+
class TestClass < ActionView::Base; end
|
6
|
+
|
7
|
+
describe "including it" do
|
8
|
+
it "should include all the view helpers" do
|
9
|
+
in_the TestClass do
|
10
|
+
include ViewModels::Helpers::View
|
11
|
+
end
|
12
|
+
|
13
|
+
TestClass.should include(ActionView::Helpers)
|
14
|
+
TestClass.should include(ERB::Util)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Base do
|
4
|
+
|
5
|
+
describe "readers" do
|
6
|
+
describe "model" do
|
7
|
+
before(:each) do
|
8
|
+
@model = stub :model
|
9
|
+
@view_model = ViewModels::Base.new @model, nil
|
10
|
+
end
|
11
|
+
it "should have a reader" do
|
12
|
+
in_the @view_model do
|
13
|
+
model.should == @model
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
describe "controller" do
|
18
|
+
before(:each) do
|
19
|
+
@context = stub :controller
|
20
|
+
@view_model = ViewModels::Base.new nil, @context
|
21
|
+
end
|
22
|
+
it "should have a reader" do
|
23
|
+
in_the @view_model do
|
24
|
+
controller.should == @context
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "context recognition" do
|
31
|
+
describe "context is a view" do
|
32
|
+
before(:each) do
|
33
|
+
@view = stub :view, :controller => 'controller'
|
34
|
+
@view_model = ViewModels::Base.new nil, @view
|
35
|
+
end
|
36
|
+
it "should get the controller from the view" do
|
37
|
+
in_the @view_model do
|
38
|
+
controller.should == 'controller'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
describe "context is a controller" do
|
43
|
+
before(:each) do
|
44
|
+
@controller = stub :controller
|
45
|
+
@view_model = ViewModels::Base.new nil, @controller
|
46
|
+
end
|
47
|
+
it "should just use it for the controller" do
|
48
|
+
expected = @controller
|
49
|
+
in_the @view_model do
|
50
|
+
controller.should == expected
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ".master_helper_module" do
|
57
|
+
before(:each) do
|
58
|
+
class ViewModels::SpecificMasterHelperModule < ViewModels::Base; end
|
59
|
+
end
|
60
|
+
it "should be a class specific inheritable accessor" do
|
61
|
+
ViewModels::SpecificMasterHelperModule.master_helper_module = :some_value
|
62
|
+
ViewModels::SpecificMasterHelperModule.master_helper_module.should == :some_value
|
63
|
+
end
|
64
|
+
it "should be an instance of Module on Base" do
|
65
|
+
ViewModels::Base.master_helper_module.should be_instance_of(Module)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe ".controller_method" do
|
70
|
+
it "should set up delegate calls to the context/controller" do
|
71
|
+
ViewModels::Base.should_receive(:delegate).once.with(:method1, :method2, :to => :context)
|
72
|
+
|
73
|
+
ViewModels::Base.controller_method :method1, :method2
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe ".helper" do
|
78
|
+
it "should include the helper" do
|
79
|
+
helper_module = Module.new
|
80
|
+
|
81
|
+
ViewModels::Base.should_receive(:include).once.with helper_module
|
82
|
+
|
83
|
+
ViewModels::Base.helper helper_module
|
84
|
+
end
|
85
|
+
it "should include the helper in the master helper module" do
|
86
|
+
master_helper_module = Module.new
|
87
|
+
ViewModels::Base.should_receive(:master_helper_module).and_return master_helper_module
|
88
|
+
|
89
|
+
helper_module = Module.new
|
90
|
+
master_helper_module.should_receive(:include).once.with helper_module
|
91
|
+
|
92
|
+
ViewModels::Base.helper helper_module
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#logger" do
|
97
|
+
it "should delegate to the controller" do
|
98
|
+
controller = stub :controller
|
99
|
+
view_model = ViewModels::Base.new nil, controller
|
100
|
+
|
101
|
+
controller.should_receive(:logger).once
|
102
|
+
|
103
|
+
in_the view_model do
|
104
|
+
logger
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::View do
|
4
|
+
|
5
|
+
it "should be initializable" do
|
6
|
+
controller_class = stub :controller_class, :view_paths => ActionView::PathSet.new
|
7
|
+
controller = stub :controller, :class => controller_class
|
8
|
+
|
9
|
+
ViewModels::View.new controller, Module.new
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Helpers::Mapping::Collection do
|
4
|
+
include ViewModels::Helpers::Mapping
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@collection = stub :collection
|
8
|
+
@context = stub :context
|
9
|
+
@collection_view_model = ViewModels::Helpers::Mapping::Collection.new @collection, @context
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "collection_view_model_for" do
|
13
|
+
it "should return kind of a ViewModels::Collection" do
|
14
|
+
collection_view_model_for([]).should be_kind_of ViewModels::Helpers::Mapping::Collection
|
15
|
+
end
|
16
|
+
it "should pass any parameters directly through" do
|
17
|
+
collection = stub :collection
|
18
|
+
context = stub :context
|
19
|
+
ViewModels::Helpers::Mapping::Collection.should_receive(:new).with(collection, context).once
|
20
|
+
collection_view_model_for collection, context
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "list" do
|
25
|
+
it "should call render_partial and return the rendered result" do
|
26
|
+
@collection_view_model.stub! :render_partial => :result
|
27
|
+
|
28
|
+
@collection_view_model.list.should == :result
|
29
|
+
end
|
30
|
+
it "should call render_partial with the right parameters" do
|
31
|
+
default_options = {
|
32
|
+
:collection => @collection,
|
33
|
+
:template_name => :list_item,
|
34
|
+
:separator => nil
|
35
|
+
}
|
36
|
+
|
37
|
+
@collection_view_model.should_receive(:render_partial).once.with :list, default_options
|
38
|
+
|
39
|
+
@collection_view_model.list
|
40
|
+
end
|
41
|
+
it "should override the default options if specific options are given" do
|
42
|
+
specific_options = {
|
43
|
+
:collection => :a,
|
44
|
+
:template_name => :c,
|
45
|
+
:separator => :d
|
46
|
+
}
|
47
|
+
|
48
|
+
@collection_view_model.should_receive(:render_partial).once.with :list, specific_options
|
49
|
+
|
50
|
+
@collection_view_model.list specific_options
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "collection" do
|
55
|
+
it "should call render_partial and return the rendered result" do
|
56
|
+
@collection_view_model.stub! :render_partial => :result
|
57
|
+
|
58
|
+
@collection_view_model.collection.should == :result
|
59
|
+
end
|
60
|
+
it "should call render_partial with the right parameters" do
|
61
|
+
default_options = {
|
62
|
+
:collection => @collection,
|
63
|
+
:template_name => :collection_item,
|
64
|
+
:separator => nil
|
65
|
+
}
|
66
|
+
@collection_view_model.should_receive(:render_partial).once.with :collection, default_options
|
67
|
+
|
68
|
+
@collection_view_model.collection
|
69
|
+
end
|
70
|
+
it "should override the default options if specific options are given" do
|
71
|
+
specific_options = {
|
72
|
+
:collection => :a,
|
73
|
+
:template_name => :c,
|
74
|
+
:separator => :d
|
75
|
+
}
|
76
|
+
|
77
|
+
@collection_view_model.should_receive(:render_partial).once.with :collection, specific_options
|
78
|
+
|
79
|
+
@collection_view_model.collection specific_options
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "table" do
|
84
|
+
it "should call render_partial and return the rendered result" do
|
85
|
+
@collection_view_model.stub! :render_partial => :result
|
86
|
+
|
87
|
+
@collection_view_model.table.should == :result
|
88
|
+
end
|
89
|
+
it "should call render_partial with the right parameters" do
|
90
|
+
default_options = {
|
91
|
+
:collection => @collection,
|
92
|
+
:template_name => :table_row,
|
93
|
+
:separator => nil
|
94
|
+
}
|
95
|
+
|
96
|
+
@collection_view_model.should_receive(:render_partial).once.with :table, default_options
|
97
|
+
|
98
|
+
@collection_view_model.table
|
99
|
+
end
|
100
|
+
it "should override the default options if specific options are given" do
|
101
|
+
specific_options = {
|
102
|
+
:collection => :a,
|
103
|
+
:template_name => :c,
|
104
|
+
:separator => :d
|
105
|
+
}
|
106
|
+
|
107
|
+
@collection_view_model.should_receive(:render_partial).once.with :table, specific_options
|
108
|
+
|
109
|
+
@collection_view_model.table(specific_options)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "pagination" do
|
114
|
+
it "should call render_partial and return the rendered result" do
|
115
|
+
@collection_view_model.stub! :render_partial => :result
|
116
|
+
|
117
|
+
@collection_view_model.pagination.should == :result
|
118
|
+
end
|
119
|
+
it "should call render_partial with the right parameters" do
|
120
|
+
default_options = {
|
121
|
+
:collection => @collection,
|
122
|
+
:separator => '|'
|
123
|
+
}
|
124
|
+
@collection_view_model.should_receive(:render_partial).once.with :pagination, default_options
|
125
|
+
|
126
|
+
@collection_view_model.pagination
|
127
|
+
end
|
128
|
+
it "should override the default options if specific options are given" do
|
129
|
+
specific_options = {
|
130
|
+
:collection => :a,
|
131
|
+
:separator => :c
|
132
|
+
}
|
133
|
+
@collection_view_model.should_receive(:render_partial).once.with :pagination, specific_options
|
134
|
+
|
135
|
+
@collection_view_model.pagination specific_options
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "delegation" do
|
140
|
+
describe "enumerable" do
|
141
|
+
Enumerable.instance_methods.map(&:to_sym).each do |method|
|
142
|
+
it "should delegate #{method} to the collection" do
|
143
|
+
@collection.should_receive(method).once
|
144
|
+
|
145
|
+
@collection_view_model.send method
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
describe "array" do
|
150
|
+
describe "length" do
|
151
|
+
it "should delegate to #length of the collection" do
|
152
|
+
@collection.should_receive(:length).once
|
153
|
+
|
154
|
+
@collection_view_model.length
|
155
|
+
end
|
156
|
+
it "should return the length of the collection" do
|
157
|
+
@collection.should_receive(:length).and_return :this_length
|
158
|
+
|
159
|
+
@collection_view_model.length.should == :this_length
|
160
|
+
end
|
161
|
+
it "should alias size" do
|
162
|
+
@collection.should_receive(:size).and_return :this_length
|
163
|
+
|
164
|
+
@collection_view_model.size.should == :this_length
|
165
|
+
end
|
166
|
+
end
|
167
|
+
describe "empty?" do
|
168
|
+
it "should delegate to #empty? of the collection" do
|
169
|
+
@collection.should_receive(:empty?).once
|
170
|
+
|
171
|
+
@collection_view_model.empty?
|
172
|
+
end
|
173
|
+
it "should return whatever #empty? of the collection returns" do
|
174
|
+
@collection.should_receive(:empty?).and_return :true_or_false
|
175
|
+
|
176
|
+
@collection_view_model.empty?.should == :true_or_false
|
177
|
+
end
|
178
|
+
end
|
179
|
+
describe "each" do
|
180
|
+
it "should delegate to #each of the collection" do
|
181
|
+
proc = stub :proc
|
182
|
+
|
183
|
+
@collection.should_receive(:each).with(proc).once
|
184
|
+
|
185
|
+
@collection_view_model.each proc
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../../spec_helper')
|
2
|
+
|
3
|
+
describe ViewModels::Helpers::Mapping do
|
4
|
+
include ViewModels::Helpers::Mapping
|
5
|
+
|
6
|
+
describe "view_model_for" do
|
7
|
+
it "should just pass the params through to the view_model" do
|
8
|
+
class SomeModelClazz; end
|
9
|
+
class ViewModels::SomeModelClazz < ViewModels::Base; end
|
10
|
+
context = stub :context
|
11
|
+
self.stub! :default_view_model_class_for => ViewModels::SomeModelClazz
|
12
|
+
model = SomeModelClazz.new
|
13
|
+
|
14
|
+
ViewModels::SomeModelClazz.should_receive(:new).once.with model, context
|
15
|
+
|
16
|
+
view_model_for model, context
|
17
|
+
end
|
18
|
+
describe "specific_view_model_mapping" do
|
19
|
+
it "should return an empty hash by default" do
|
20
|
+
specific_view_model_mapping.should == {}
|
21
|
+
end
|
22
|
+
it "should raise an ArgumentError on an non-mapped model" do
|
23
|
+
class SomeViewModelClass; end
|
24
|
+
specific_view_model_mapping[String] = SomeViewModelClass
|
25
|
+
lambda {
|
26
|
+
view_model_for("Some String")
|
27
|
+
}.should raise_error(ArgumentError, "wrong number of arguments (2 for 0)")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
describe "no specific mapping" do
|
31
|
+
it "should raise on an non-mapped model" do
|
32
|
+
lambda {
|
33
|
+
view_model_for(42)
|
34
|
+
}.should raise_error(NameError, "uninitialized constant ViewModels::Fixnum")
|
35
|
+
end
|
36
|
+
it "should return a default view_model instance" do
|
37
|
+
class SomeModelClazz; end
|
38
|
+
class ViewModels::SomeModelClazz < ViewModels::Base; end
|
39
|
+
view_model_for(SomeModelClazz.new).should be_instance_of ViewModels::SomeModelClazz
|
40
|
+
end
|
41
|
+
end
|
42
|
+
describe "with specific mapping" do
|
43
|
+
class SomeModelClazz; end
|
44
|
+
class ViewModels::SomeSpecificClazz < ViewModels::Base; end
|
45
|
+
before(:each) do
|
46
|
+
self.should_receive(:specific_view_model_mapping).any_number_of_times.and_return SomeModelClazz => ViewModels::SomeSpecificClazz
|
47
|
+
end
|
48
|
+
it "should return a specifically mapped view_model instance" do
|
49
|
+
view_model_for(SomeModelClazz.new).should be_instance_of ViewModels::SomeSpecificClazz
|
50
|
+
end
|
51
|
+
it "should not call #default_view_model_class_for" do
|
52
|
+
mock(self).should_receive(:default_view_model_class_for).never
|
53
|
+
view_model_for SomeModelClazz.new
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "default_view_model_class_for" do
|
59
|
+
it "should return a class with ViewModels:: prepended" do
|
60
|
+
class Gaga; end # The model.
|
61
|
+
class ViewModels::Gaga < ViewModels::Base; end
|
62
|
+
default_view_model_class_for(Gaga.new).should == ViewModels::Gaga
|
63
|
+
end
|
64
|
+
it "should raise a NameError if the Presenter class does not exist" do
|
65
|
+
class Brrzt; end # Just the model.
|
66
|
+
lambda {
|
67
|
+
default_view_model_class_for(Brrzt.new)
|
68
|
+
}.should raise_error(NameError, "uninitialized constant ViewModels::Brrzt")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 13
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 2.0.
|
9
|
+
- 1
|
10
|
+
version: 2.0.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Florian Hanke
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date:
|
21
|
+
date: 2011-04-10 00:00:00 +10:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -63,14 +63,23 @@ extra_rdoc_files: []
|
|
63
63
|
|
64
64
|
files:
|
65
65
|
- lib/init.rb
|
66
|
-
- lib/
|
66
|
+
- lib/view_models.rb
|
67
|
+
- lib/shared/init.rb
|
68
|
+
- lib/shared/lib/view_models/base.rb
|
69
|
+
- lib/shared/lib/view_models/context_extractor.rb
|
70
|
+
- lib/shared/lib/view_models/extensions/active_record.rb
|
71
|
+
- lib/shared/lib/view_models/extensions/model_reader.rb
|
72
|
+
- lib/shared/lib/view_models/helpers/collection.rb
|
73
|
+
- lib/shared/lib/view_models/helpers/mapping.rb
|
74
|
+
- lib/shared/lib/view_models/path_store.rb
|
75
|
+
- lib/shared/lib/view_models/render_options.rb
|
76
|
+
- lib/shared/lib/view_models.rb
|
77
|
+
- lib/shared/README.textile
|
67
78
|
- lib/padrino/init.rb
|
68
79
|
- lib/padrino/lib/helpers/collection.rb
|
69
80
|
- lib/padrino/lib/padrino/view_models.rb
|
70
81
|
- lib/padrino/lib/view_models/base.rb
|
71
|
-
- lib/
|
72
|
-
- lib/rails2/TODO.textile
|
73
|
-
- lib/rails2/generators/view_models/USAGE
|
82
|
+
- lib/padrino/README.textile
|
74
83
|
- lib/rails2/generators/view_models/templates/README
|
75
84
|
- lib/rails2/generators/view_models/templates/spec/view_model_spec.rb
|
76
85
|
- lib/rails2/generators/view_models/templates/view_models/view_model.rb
|
@@ -84,28 +93,30 @@ files:
|
|
84
93
|
- lib/rails2/generators/view_models/templates/views/view_models/collection/_pagination.text.erb
|
85
94
|
- lib/rails2/generators/view_models/templates/views/view_models/collection/_table.html.haml
|
86
95
|
- lib/rails2/generators/view_models/templates/views/view_models/collection/_table.text.erb
|
96
|
+
- lib/rails2/generators/view_models/USAGE
|
87
97
|
- lib/rails2/generators/view_models/view_models_generator.rb
|
88
98
|
- lib/rails2/init.rb
|
89
|
-
- lib/rails2/lib/experimental/README.textile
|
90
99
|
- lib/rails2/lib/experimental/modules_in_render_hierarchy.rb
|
100
|
+
- lib/rails2/lib/experimental/README.textile
|
91
101
|
- lib/rails2/lib/extensions/view.rb
|
92
102
|
- lib/rails2/lib/helpers/collection.rb
|
93
103
|
- lib/rails2/lib/helpers/view.rb
|
94
|
-
- lib/rails2/lib/view_models.rb
|
95
104
|
- lib/rails2/lib/view_models/base.rb
|
96
105
|
- lib/rails2/lib/view_models/view.rb
|
97
|
-
- lib/
|
98
|
-
- lib/
|
99
|
-
- lib/
|
100
|
-
-
|
101
|
-
-
|
102
|
-
-
|
103
|
-
-
|
104
|
-
-
|
105
|
-
-
|
106
|
-
-
|
107
|
-
-
|
108
|
-
- lib/view_models.rb
|
106
|
+
- lib/rails2/lib/view_models.rb
|
107
|
+
- lib/rails2/README.textile
|
108
|
+
- lib/rails2/TODO.textile
|
109
|
+
- spec/padrino/integration/integration_spec.rb
|
110
|
+
- spec/padrino/lib/helpers/collection_spec.rb
|
111
|
+
- spec/rails2/integration/integration_spec.rb
|
112
|
+
- spec/rails2/lib/extensions/active_record_spec.rb
|
113
|
+
- spec/rails2/lib/extensions/model_reader_spec.rb
|
114
|
+
- spec/rails2/lib/helpers/collection_spec.rb
|
115
|
+
- spec/rails2/lib/helpers/view_spec.rb
|
116
|
+
- spec/rails2/lib/view_models/base_spec.rb
|
117
|
+
- spec/rails2/lib/view_models/view_spec.rb
|
118
|
+
- spec/shared/lib/helpers/collection_spec.rb
|
119
|
+
- spec/shared/lib/helpers/mapping_spec.rb
|
109
120
|
has_rdoc: true
|
110
121
|
homepage: http://floere.github.com/view_models
|
111
122
|
licenses: []
|
@@ -137,9 +148,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
148
|
requirements: []
|
138
149
|
|
139
150
|
rubyforge_project:
|
140
|
-
rubygems_version: 1.
|
151
|
+
rubygems_version: 1.4.2
|
141
152
|
signing_key:
|
142
153
|
specification_version: 3
|
143
154
|
summary: A model proxy for Rails views. Helps you keep the representation of a model and the model itself separate.
|
144
|
-
test_files:
|
145
|
-
|
155
|
+
test_files:
|
156
|
+
- spec/padrino/integration/integration_spec.rb
|
157
|
+
- spec/padrino/lib/helpers/collection_spec.rb
|
158
|
+
- spec/rails2/integration/integration_spec.rb
|
159
|
+
- spec/rails2/lib/extensions/active_record_spec.rb
|
160
|
+
- spec/rails2/lib/extensions/model_reader_spec.rb
|
161
|
+
- spec/rails2/lib/helpers/collection_spec.rb
|
162
|
+
- spec/rails2/lib/helpers/view_spec.rb
|
163
|
+
- spec/rails2/lib/view_models/base_spec.rb
|
164
|
+
- spec/rails2/lib/view_models/view_spec.rb
|
165
|
+
- spec/shared/lib/helpers/collection_spec.rb
|
166
|
+
- spec/shared/lib/helpers/mapping_spec.rb
|