autoforme 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +10 -0
- data/Rakefile +7 -2
- data/lib/autoforme.rb +1 -1
- data/lib/autoforme/action.rb +15 -21
- data/lib/autoforme/frameworks/rails.rb +4 -4
- data/lib/autoforme/frameworks/roda.rb +5 -1
- data/lib/autoforme/frameworks/sinatra.rb +2 -2
- data/lib/autoforme/model.rb +3 -10
- data/lib/autoforme/models/sequel.rb +1 -6
- data/lib/autoforme/table.rb +1 -8
- data/lib/autoforme/version.rb +1 -1
- data/spec/all.rb +2 -0
- data/spec/associations_spec.rb +145 -19
- data/spec/basic_spec.rb +229 -44
- data/spec/mtm_spec.rb +86 -9
- data/spec/rails_spec_helper.rb +1 -1
- data/spec/roda_spec.rb +72 -0
- data/spec/spec_helper.rb +26 -2
- data/spec/unit_spec.rb +62 -1
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7431cd2d4051bea42ed58879c0d0418de7282b5d
|
4
|
+
data.tar.gz: f8d7d4c14152aef6efeedd2fb763df6cd3d4e77d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3047d058fccd77841b9caa2855e9f9a0ecbb54e975c44586c68d01ddcdc5a06a10769ed7f207740318b0be748b7becff1b2f3178ef5fcb5ee8a17d661d65dfb0
|
7
|
+
data.tar.gz: 82b9b6c81507bae202145f7b4af5d1eec35eec0bade86491a08a389a85896849d5f5c2d0f5ce524ee25fab51bb5f250dd6d1caa9166e9e4196e9e7df761f99cc
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 1.5.0 (2016-11-18)
|
2
|
+
|
3
|
+
* Allow autocompleting for associated objects even if current class doesn't support autocompleting (jeremyevans)
|
4
|
+
|
5
|
+
* [SECURITY] Fix check for non-idempotent GET requests (jeremyevans)
|
6
|
+
|
7
|
+
* Fix some deprecation warnings on Rails 5 (jeremyevans)
|
8
|
+
|
9
|
+
* Make sinatra routes handle namespaced models by default (jeremyevans)
|
10
|
+
|
1
11
|
=== 1.4.0 (2016-05-18)
|
2
12
|
|
3
13
|
* Handle selecting a blank object during show/edit/delete/mtm_edit by showing the same page (jeremyevans)
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ end
|
|
12
12
|
|
13
13
|
spec = proc do |env|
|
14
14
|
env.each{|k,v| ENV[k] = v}
|
15
|
-
sh "#{FileUtils::RUBY}
|
15
|
+
sh "#{FileUtils::RUBY} spec/all.rb"
|
16
16
|
env.each{|k,v| ENV.delete(k)}
|
17
17
|
end
|
18
18
|
task :default => :roda_spec
|
@@ -30,10 +30,15 @@ task :spec => spec_tasks
|
|
30
30
|
spec.call('FRAMEWORK'=>framework)
|
31
31
|
end
|
32
32
|
|
33
|
-
desc "Run specs with for #{framework}"
|
33
|
+
desc "Run specs with coverage for #{framework}"
|
34
34
|
task "#{framework}_spec_cov" do
|
35
35
|
spec.call('FRAMEWORK'=>framework, 'COVERAGE'=>'1')
|
36
36
|
end
|
37
|
+
|
38
|
+
desc "Run specs with -w for #{framework}, some warnings filtered"
|
39
|
+
task "#{framework}_spec_w" do
|
40
|
+
spec.call('FRAMEWORK'=>framework, 'RUBYOPT'=>'-w', 'WARNING'=>'1')
|
41
|
+
end
|
37
42
|
end
|
38
43
|
|
39
44
|
### RDoc
|
data/lib/autoforme.rb
CHANGED
@@ -27,7 +27,7 @@ module AutoForme
|
|
27
27
|
unless klass = @mutex.synchronize{map[type]}
|
28
28
|
require "autoforme/#{map_type}s/#{type}"
|
29
29
|
unless klass = @mutex.synchronize{map[type]}
|
30
|
-
raise Error, "unsupported
|
30
|
+
raise Error, "unsupported #{map_type}: #{type.inspect}"
|
31
31
|
end
|
32
32
|
end
|
33
33
|
klass
|
data/lib/autoforme/action.rb
CHANGED
@@ -34,7 +34,7 @@ module AutoForme
|
|
34
34
|
ALL_SUPPORTED_ACTIONS = %w'new create show edit update delete destroy browse search mtm_edit mtm_update association_links autocomplete'.freeze
|
35
35
|
|
36
36
|
# Map of regular type symbols to normalized type symbols
|
37
|
-
NORMALIZED_ACTION_MAP = {:create=>:new, :update=>:edit, :destroy=>:delete, :mtm_update=>:mtm_edit}
|
37
|
+
NON_IDEMPOTENT_TYPES = NORMALIZED_ACTION_MAP = {:create=>:new, :update=>:edit, :destroy=>:delete, :mtm_update=>:mtm_edit}
|
38
38
|
|
39
39
|
# Map of type symbols to HTML titles
|
40
40
|
TITLE_MAP = {:new=>'New', :show=>'Show', :edit=>'Edit', :delete=>'Delete', :browse=>'Browse', :search=>'Search', :mtm_edit=>'Many To Many Edit'}
|
@@ -53,11 +53,10 @@ module AutoForme
|
|
53
53
|
#
|
54
54
|
# As a side-effect, this sets up additional state related to the request.
|
55
55
|
def supported?
|
56
|
-
return false unless idempotent? || request.post?
|
57
56
|
return false unless ALL_SUPPORTED_ACTIONS.include?(request.action_type)
|
58
|
-
|
59
|
-
@
|
60
|
-
|
57
|
+
type = @type = request.action_type.to_sym
|
58
|
+
@normalized_type = NORMALIZED_ACTION_MAP.fetch(type, type)
|
59
|
+
return false if NON_IDEMPOTENT_TYPES[type] && !request.post?
|
61
60
|
|
62
61
|
case type
|
63
62
|
when :mtm_edit
|
@@ -79,10 +78,12 @@ module AutoForme
|
|
79
78
|
return false unless model.association?(assoc)
|
80
79
|
@params_association = assoc.to_sym
|
81
80
|
@subtype = :association
|
81
|
+
return false unless associated_class = model.associated_model_class(@params_association)
|
82
|
+
return false unless associated_class.autocomplete_options_for(@subtype, request)
|
82
83
|
else
|
83
84
|
@subtype = subtype
|
85
|
+
return false unless model.autocomplete_options_for(@subtype, request)
|
84
86
|
end
|
85
|
-
return false unless model.autocomplete_options_for(@subtype, request)
|
86
87
|
else
|
87
88
|
return false unless model.supported_action?(normalized_type, request)
|
88
89
|
|
@@ -99,11 +100,6 @@ module AutoForme
|
|
99
100
|
Rack::Utils.escape_html(s.to_s)
|
100
101
|
end
|
101
102
|
|
102
|
-
# Return whether the current action is an idempotent action.
|
103
|
-
def idempotent?
|
104
|
-
type == normalized_type
|
105
|
-
end
|
106
|
-
|
107
103
|
# Get request parameters for the model. Used when retrieving form
|
108
104
|
# values that use namespacing.
|
109
105
|
def model_params
|
@@ -140,8 +136,6 @@ module AutoForme
|
|
140
136
|
"edit/#{model.primary_key_value(obj)}"
|
141
137
|
when :mtm_edit
|
142
138
|
"mtm_edit/#{model.primary_key_value(obj)}?association=#{params_association}"
|
143
|
-
else
|
144
|
-
raise Error, "Unhandled redirect type: #{type.inspect}"
|
145
139
|
end
|
146
140
|
path = url_for(path)
|
147
141
|
end
|
@@ -319,13 +313,13 @@ module AutoForme
|
|
319
313
|
end
|
320
314
|
t << '</table>'
|
321
315
|
if type == :show && model.supported_action?(:edit, request)
|
322
|
-
t << Forme.form(form_attributes(:action=>url_for("edit/#{model.primary_key_value(obj)}")), form_opts) do |
|
323
|
-
|
316
|
+
t << Forme.form(form_attributes(:action=>url_for("edit/#{model.primary_key_value(obj)}")), form_opts) do |f1|
|
317
|
+
f1.button(:value=>'Edit', :class=>'btn btn-primary')
|
324
318
|
end.to_s
|
325
319
|
end
|
326
320
|
if type == :delete
|
327
|
-
t << Forme.form(form_attributes(:action=>url_for("destroy/#{model.primary_key_value(obj)}"), :method=>:post), form_opts) do |
|
328
|
-
|
321
|
+
t << Forme.form(form_attributes(:action=>url_for("destroy/#{model.primary_key_value(obj)}"), :method=>:post), form_opts) do |f1|
|
322
|
+
f1.button(:value=>'Delete', :class=>'btn btn-danger')
|
329
323
|
end.to_s
|
330
324
|
else
|
331
325
|
t << association_links(obj)
|
@@ -473,7 +467,7 @@ module AutoForme
|
|
473
467
|
# Handle the mtm_edit action by showing a list page if there is no model object selected, a list of associations for that model
|
474
468
|
# if there is a model object but no association selected, or a mtm_edit form if there is a model object and association selected.
|
475
469
|
def handle_mtm_edit
|
476
|
-
if
|
470
|
+
if request.id
|
477
471
|
obj = model.with_pk(:edit, request, request.id)
|
478
472
|
unless assoc = params_association
|
479
473
|
options = model.mtm_association_select_options(request)
|
@@ -520,7 +514,7 @@ module AutoForme
|
|
520
514
|
assoc_obj = model.mtm_update(request, assoc, obj, request.params['add'], request.params['remove'])
|
521
515
|
request.set_flash_notice("Updated #{assoc} association for #{model.class_name}") unless request.xhr?
|
522
516
|
if request.xhr?
|
523
|
-
if
|
517
|
+
if request.params['add']
|
524
518
|
@type = :edit
|
525
519
|
mtm_edit_remove(assoc, model.associated_model_class(assoc), obj, assoc_obj)
|
526
520
|
else
|
@@ -599,9 +593,9 @@ module AutoForme
|
|
599
593
|
|
600
594
|
unless assoc_objs.empty?
|
601
595
|
t << "<ul>\n"
|
602
|
-
assoc_objs.each do |
|
596
|
+
assoc_objs.each do |assoc_obj1|
|
603
597
|
t << "<li>"
|
604
|
-
t << association_link(mc,
|
598
|
+
t << association_link(mc, assoc_obj1)
|
605
599
|
t << "</li>"
|
606
600
|
end
|
607
601
|
t << "</ul>"
|
@@ -8,7 +8,7 @@ module AutoForme
|
|
8
8
|
@controller = request
|
9
9
|
@params = request.params
|
10
10
|
@session = request.session
|
11
|
-
@env = request.env
|
11
|
+
@env = request.request.env
|
12
12
|
@method = @env['REQUEST_METHOD']
|
13
13
|
@model = @params['autoforme_model']
|
14
14
|
@action_type = @params['autoforme_action']
|
@@ -54,14 +54,14 @@ module AutoForme
|
|
54
54
|
elsif @autoforme_action.output_type == 'csv'
|
55
55
|
response.headers['Content-Type'] = 'text/csv'
|
56
56
|
response.headers['Content-Disposition'] = "attachment; filename=#{@autoforme_action.output_filename}"
|
57
|
-
render :
|
57
|
+
render :body=>@autoforme_text
|
58
58
|
elsif @autoforme_action.request.xhr?
|
59
|
-
render :
|
59
|
+
render :html=>@autoforme_text.html_safe
|
60
60
|
else
|
61
61
|
render :inline=>"<%=raw @autoforme_text %>", :layout=>true
|
62
62
|
end
|
63
63
|
else
|
64
|
-
render :
|
64
|
+
render :plain=>'Unhandled Request', :status=>404
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -18,7 +18,9 @@ module AutoForme
|
|
18
18
|
remaining_path = if @request.respond_to?(:remaining_path)
|
19
19
|
@request.remaining_path
|
20
20
|
else
|
21
|
+
# :nocov:
|
21
22
|
@env['PATH_INFO']
|
23
|
+
# :nocov:
|
22
24
|
end
|
23
25
|
|
24
26
|
path_id = $1 if remaining_path =~ %r{\A\/([\w-]+)\z}
|
@@ -59,11 +61,13 @@ module AutoForme
|
|
59
61
|
path = if r.respond_to?(:matched_path)
|
60
62
|
r.matched_path
|
61
63
|
else
|
64
|
+
# :nocov:
|
62
65
|
r.env['SCRIPT_NAME']
|
66
|
+
# :nocov:
|
63
67
|
end
|
64
68
|
current_matchers = matchers + [lambda{@autoforme_action = framework.action_for(Request.new(self, path))}]
|
65
69
|
|
66
|
-
r.on
|
70
|
+
r.on(*current_matchers) do
|
67
71
|
@autoforme_text = @autoforme_action.handle
|
68
72
|
if @autoforme_action.output_type == 'csv'
|
69
73
|
response['Content-Type'] = 'text/csv'
|
@@ -58,8 +58,8 @@ module AutoForme
|
|
58
58
|
end
|
59
59
|
|
60
60
|
prefix = Regexp.escape(framework.prefix) if framework.prefix
|
61
|
-
@controller.get %r{\A#{prefix}/(\w+)/(\w+)(?:/([\w-]+))?\z}, &block
|
62
|
-
@controller.post %r{\A#{prefix}/(\w+)/(\w+)(?:/([\w-]+))?\z}, &block
|
61
|
+
@controller.get %r{\A#{prefix}/([\w:]+)/(\w+)(?:/([\w-]+))?\z}, &block
|
62
|
+
@controller.post %r{\A#{prefix}/([\w:]+)/(\w+)(?:/([\w-]+))?\z}, &block
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
data/lib/autoforme/model.rb
CHANGED
@@ -319,15 +319,8 @@ module AutoForme
|
|
319
319
|
end
|
320
320
|
|
321
321
|
# An array of pairs for the select options to return for the given type.
|
322
|
-
def select_options(type, request
|
323
|
-
|
324
|
-
when Symbol, String
|
325
|
-
all_rows_for(type, request).map{|obj| [obj.send(nm), primary_key_value(obj)]}
|
326
|
-
when nil
|
327
|
-
all_rows_for(type, request).map{|obj| [object_display_name(type, request, obj), primary_key_value(obj)]}
|
328
|
-
else
|
329
|
-
all_rows_for(type, request).map{|obj| [nm.call(obj), primary_key_value(obj)]}
|
330
|
-
end
|
322
|
+
def select_options(type, request)
|
323
|
+
all_rows_for(type, request).map{|obj| [object_display_name(type, request, obj), primary_key_value(obj)]}
|
331
324
|
end
|
332
325
|
|
333
326
|
# A human readable string representing the object.
|
@@ -335,7 +328,7 @@ module AutoForme
|
|
335
328
|
apply_name_method(display_name_for, obj, type, request).to_s
|
336
329
|
end
|
337
330
|
|
338
|
-
# A human
|
331
|
+
# A human readable string for the associated object.
|
339
332
|
def associated_object_display_name(assoc, request, obj)
|
340
333
|
apply_name_method(column_options_for(:mtm_edit, request, assoc)[:name_method], obj, :mtm_edit, request)
|
341
334
|
end
|
@@ -21,11 +21,6 @@ module AutoForme
|
|
21
21
|
S::Model
|
22
22
|
end
|
23
23
|
|
24
|
-
# A completely empty search object, with no defaults.
|
25
|
-
def new_search
|
26
|
-
model.call({})
|
27
|
-
end
|
28
|
-
|
29
24
|
# The name of the form param for the given association.
|
30
25
|
def form_param_name(assoc)
|
31
26
|
"#{model.send(:underscore, model.name)}[#{association_key(assoc)}]"
|
@@ -279,7 +274,7 @@ module AutoForme
|
|
279
274
|
display = display.call(callback_opts) if display.respond_to?(:call)
|
280
275
|
limit = opts[:limit] || 10
|
281
276
|
limit = limit.call(callback_opts) if limit.respond_to?(:call)
|
282
|
-
opts[:filter] ||= lambda{|
|
277
|
+
opts[:filter] ||= lambda{|ds1, _| ds1.where(S.ilike(display, "%#{ds.escape_like(query)}%"))}
|
283
278
|
ds = opts[:filter].call(ds, callback_opts)
|
284
279
|
ds = ds.select(S.join([S.qualify(model.table_name, model.primary_key), display], ' - ').as(:v)).
|
285
280
|
limit(limit)
|
data/lib/autoforme/table.rb
CHANGED
@@ -21,17 +21,13 @@ module AutoForme
|
|
21
21
|
# An array of objects to show in the table
|
22
22
|
attr_reader :objs
|
23
23
|
|
24
|
-
|
25
|
-
attr_reader :opts
|
26
|
-
|
27
|
-
def initialize(action, objs, opts={})
|
24
|
+
def initialize(action, objs)
|
28
25
|
@action = action
|
29
26
|
@request = action.request
|
30
27
|
@model = action.model
|
31
28
|
@type = action.normalized_type
|
32
29
|
@columns = model.columns_for(type, request)
|
33
30
|
@objs = objs
|
34
|
-
@opts = opts
|
35
31
|
end
|
36
32
|
|
37
33
|
def h(s)
|
@@ -42,9 +38,6 @@ module AutoForme
|
|
42
38
|
def to_s
|
43
39
|
html = String.new
|
44
40
|
html << "<table id=\"autoforme_table\" class=\"#{model.table_class_for(type, request)}\">"
|
45
|
-
if caption = opts[:caption]
|
46
|
-
html << "<caption>#{h caption}</caption>"
|
47
|
-
end
|
48
41
|
|
49
42
|
html << "<thead><tr>"
|
50
43
|
columns.each do |column|
|
data/lib/autoforme/version.rb
CHANGED
data/spec/all.rb
ADDED
data/spec/associations_spec.rb
CHANGED
@@ -38,8 +38,8 @@ describe AutoForme do
|
|
38
38
|
click_link 'Show'
|
39
39
|
select 'Album1'
|
40
40
|
click_button 'Show'
|
41
|
-
page.html.must_match
|
42
|
-
page.html.must_match
|
41
|
+
page.html.must_match(/Name.+Album1b/m)
|
42
|
+
page.html.must_match(/Artist.+Artist2/m)
|
43
43
|
|
44
44
|
click_link 'Search'
|
45
45
|
fill_in 'Name', :with=>'1b'
|
@@ -70,6 +70,11 @@ describe AutoForme do
|
|
70
70
|
click_button 'Create'
|
71
71
|
Album.first.artist_id.must_equal a.id
|
72
72
|
|
73
|
+
click_link 'Show'
|
74
|
+
select 'Album1'
|
75
|
+
click_button 'Show'
|
76
|
+
page.body.must_include 'TestArtist'
|
77
|
+
|
73
78
|
click_link 'Edit'
|
74
79
|
select 'Album1'
|
75
80
|
click_button 'Edit'
|
@@ -83,6 +88,15 @@ describe AutoForme do
|
|
83
88
|
fill_in 'Artist', :with=>b.id.to_s
|
84
89
|
click_button 'Search'
|
85
90
|
page.all('td').map{|s| s.text}.must_equal ["Album1b", "TestArtist2", "Show", "Edit", "Delete"]
|
91
|
+
|
92
|
+
visit '/Artist/autocomplete?q=Test'
|
93
|
+
page.body.must_match(/\d+ - TestArtist\n\d+ - TestArtist2/m)
|
94
|
+
|
95
|
+
visit '/Album/autocomplete/artist?q=Test'
|
96
|
+
page.body.must_match(/\d+ - TestArtist\n\d+ - TestArtist2/m)
|
97
|
+
|
98
|
+
visit '/Album/autocomplete/artist?type=edit&q=Test'
|
99
|
+
page.body.must_match(/\d+ - TestArtist\n\d+ - TestArtist2/m)
|
86
100
|
end
|
87
101
|
|
88
102
|
it "should be able to used specified name formatting in other model" do
|
@@ -109,8 +123,8 @@ describe AutoForme do
|
|
109
123
|
click_link 'Show'
|
110
124
|
select 'Album1'
|
111
125
|
click_button 'Show'
|
112
|
-
page.html.must_match
|
113
|
-
page.html.must_match
|
126
|
+
page.html.must_match(/Name.+Album1/m)
|
127
|
+
page.html.must_match(/Artist.+A1A1/m)
|
114
128
|
|
115
129
|
click_link 'Edit'
|
116
130
|
select 'Album1'
|
@@ -152,8 +166,8 @@ describe AutoForme do
|
|
152
166
|
click_link 'Show'
|
153
167
|
select 'Album1'
|
154
168
|
click_button 'Show'
|
155
|
-
page.html.must_match
|
156
|
-
page.html.must_match
|
169
|
+
page.html.must_match(/Name.+Album1/m)
|
170
|
+
page.html.must_match(/Artist.+A1A1/m)
|
157
171
|
|
158
172
|
click_link 'Edit'
|
159
173
|
select 'Album1'
|
@@ -172,6 +186,49 @@ describe AutoForme do
|
|
172
186
|
page.all('td').map{|s| s.text}.must_equal ["Album1b", "A2A2", "Show", "Edit", "Delete"]
|
173
187
|
end
|
174
188
|
|
189
|
+
it "should be able to used specified name formatting for current association" do
|
190
|
+
app_setup do
|
191
|
+
model Artist
|
192
|
+
model Album do
|
193
|
+
columns [:name, :artist]
|
194
|
+
column_options :artist=>{:name_method=>:name}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
visit("/Artist/new")
|
199
|
+
fill_in 'Name', :with=>'A1'
|
200
|
+
click_button 'Create'
|
201
|
+
fill_in 'Name', :with=>'A2'
|
202
|
+
click_button 'Create'
|
203
|
+
|
204
|
+
visit("/Album/new")
|
205
|
+
fill_in 'Name', :with=>'Album1'
|
206
|
+
select 'A1'
|
207
|
+
click_button 'Create'
|
208
|
+
|
209
|
+
click_link 'Show'
|
210
|
+
select 'Album1'
|
211
|
+
click_button 'Show'
|
212
|
+
page.html.must_match(/Name.+Album1/m)
|
213
|
+
page.html.must_match(/Artist.+A1/m)
|
214
|
+
|
215
|
+
click_link 'Edit'
|
216
|
+
select 'Album1'
|
217
|
+
click_button 'Edit'
|
218
|
+
fill_in 'Name', :with=>'Album1b'
|
219
|
+
select 'A2'
|
220
|
+
click_button 'Update'
|
221
|
+
|
222
|
+
click_link 'Search'
|
223
|
+
fill_in 'Name', :with=>'1b'
|
224
|
+
select 'A2'
|
225
|
+
click_button 'Search'
|
226
|
+
page.all('td').map{|s| s.text}.must_equal ["Album1b", "A2", "Show", "Edit", "Delete"]
|
227
|
+
|
228
|
+
click_link 'Album'
|
229
|
+
page.all('td').map{|s| s.text}.must_equal ["Album1b", "A2", "Show", "Edit", "Delete"]
|
230
|
+
end
|
231
|
+
|
175
232
|
it "should be able to eager load associations when loading model" do
|
176
233
|
app_setup do
|
177
234
|
model Artist
|
@@ -196,8 +253,52 @@ describe AutoForme do
|
|
196
253
|
click_link 'Show'
|
197
254
|
select 'A1-Album1'
|
198
255
|
click_button 'Show'
|
199
|
-
page.html.must_match
|
200
|
-
page.html.must_match
|
256
|
+
page.html.must_match(/Name.+Album1/m)
|
257
|
+
page.html.must_match(/Artist.+A1/m)
|
258
|
+
|
259
|
+
click_link 'Edit'
|
260
|
+
select 'A1-Album1'
|
261
|
+
click_button 'Edit'
|
262
|
+
fill_in 'Name', :with=>'Album1b'
|
263
|
+
select 'A2'
|
264
|
+
click_button 'Update'
|
265
|
+
|
266
|
+
click_link 'Search'
|
267
|
+
fill_in 'Name', :with=>'1b'
|
268
|
+
select 'A2'
|
269
|
+
click_button 'Search'
|
270
|
+
page.all('td').map{|s| s.text}.must_equal ["Album1b", "A2", "Show", "Edit", "Delete"]
|
271
|
+
|
272
|
+
click_link 'Album'
|
273
|
+
page.all('td').map{|s| s.text}.must_equal ["Album1b", "A2", "Show", "Edit", "Delete"]
|
274
|
+
|
275
|
+
click_link 'Delete', :match=>:first
|
276
|
+
select 'A2-Album1b'
|
277
|
+
click_button 'Delete'
|
278
|
+
end
|
279
|
+
|
280
|
+
it "should be able to eager load associations when loading model without autoforme for associated model" do
|
281
|
+
app_setup do
|
282
|
+
model Album do
|
283
|
+
columns [:name, :artist]
|
284
|
+
eager :artist
|
285
|
+
display_name{|obj| "#{obj.associations[:artist].name}-#{obj.name}"}
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
Artist.create(:name=>'A1')
|
290
|
+
Artist.create(:name=>'A2')
|
291
|
+
|
292
|
+
visit("/Album/new")
|
293
|
+
fill_in 'Name', :with=>'Album1'
|
294
|
+
select 'A1'
|
295
|
+
click_button 'Create'
|
296
|
+
|
297
|
+
click_link 'Show'
|
298
|
+
select 'A1-Album1'
|
299
|
+
click_button 'Show'
|
300
|
+
page.html.must_match(/Name.+Album1/m)
|
301
|
+
page.html.must_match(/Artist.+A1/m)
|
201
302
|
|
202
303
|
click_link 'Edit'
|
203
304
|
select 'A1-Album1'
|
@@ -274,8 +375,8 @@ describe AutoForme do
|
|
274
375
|
page.all('select option').map{|s| s.text}.must_equal ['', 'A-Y', 'B-X', 'B-Z']
|
275
376
|
select 'B-X'
|
276
377
|
click_button 'Show'
|
277
|
-
page.html.must_match
|
278
|
-
page.html.must_match
|
378
|
+
page.html.must_match(/Name.+X/m)
|
379
|
+
page.html.must_match(/Artist.+B/m)
|
279
380
|
|
280
381
|
click_link 'Edit'
|
281
382
|
page.all('select option').map{|s| s.text}.must_equal ['', 'X (B)', 'Y (A)', 'Z (B)']
|
@@ -340,8 +441,8 @@ describe AutoForme do
|
|
340
441
|
click_link 'Show'
|
341
442
|
select 'D'
|
342
443
|
click_button 'Show'
|
343
|
-
page.html.must_match
|
344
|
-
page.html.must_match
|
444
|
+
page.html.must_match(/Name.+D/m)
|
445
|
+
page.html.must_match(/Artist.+Y 2/m)
|
345
446
|
|
346
447
|
click_link 'Edit'
|
347
448
|
select 'C'
|
@@ -419,6 +520,31 @@ describe AutoForme do
|
|
419
520
|
page.current_path.must_match %r{Artist/edit/\d+}
|
420
521
|
click_link 'Albums'
|
421
522
|
page.current_path.must_equal '/Album/browse'
|
523
|
+
|
524
|
+
visit "/Album/association_links/#{Artist.first.id}"
|
525
|
+
click_link 'Artist1'
|
526
|
+
click_button 'Update'
|
527
|
+
page.current_path.must_match %r{Artist/edit/\d+}
|
528
|
+
end
|
529
|
+
|
530
|
+
it "should have working associations listed without links if there is no autoforme for other model" do
|
531
|
+
app_setup do
|
532
|
+
model Artist do
|
533
|
+
association_links :all
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
visit("/Artist/new")
|
538
|
+
fill_in 'Name', :with=>'Artist1'
|
539
|
+
click_button 'Create'
|
540
|
+
|
541
|
+
Artist.first.add_album(:name=>'Album1')
|
542
|
+
click_link 'Edit'
|
543
|
+
select 'Artist1'
|
544
|
+
click_button 'Edit'
|
545
|
+
page.html.must_include 'Album1'
|
546
|
+
page.html.wont_include 'create'
|
547
|
+
page.html.wont_include '/Album'
|
422
548
|
end
|
423
549
|
|
424
550
|
it "should display but not link if the action is not supported " do
|
@@ -447,8 +573,8 @@ describe AutoForme do
|
|
447
573
|
visit("/Artist/edit")
|
448
574
|
select 'Artist1'
|
449
575
|
click_button 'Edit'
|
450
|
-
page.html.
|
451
|
-
page.html.
|
576
|
+
page.html.must_include 'Album1'
|
577
|
+
page.html.wont_include '>edit<'
|
452
578
|
end
|
453
579
|
|
454
580
|
it "should support lazy loading association links on show and edit pages" do
|
@@ -471,7 +597,7 @@ describe AutoForme do
|
|
471
597
|
click_link 'Edit'
|
472
598
|
select 'Artist1'
|
473
599
|
click_button 'Edit'
|
474
|
-
page.html.
|
600
|
+
page.html.wont_include 'create'
|
475
601
|
click_link 'Show Associations'
|
476
602
|
click_link 'create'
|
477
603
|
fill_in 'Name', :with=>'Album1'
|
@@ -545,8 +671,8 @@ describe AutoForme do
|
|
545
671
|
click_link 'Show'
|
546
672
|
select 'Album1'
|
547
673
|
click_button 'Show'
|
548
|
-
page.html.must_match
|
549
|
-
page.html.must_match
|
674
|
+
page.html.must_match(/Name.+Album1b/m)
|
675
|
+
page.html.must_match(/Artist.+Artist2/m)
|
550
676
|
|
551
677
|
click_link 'Search'
|
552
678
|
fill_in 'Name', :with=>'1b'
|
@@ -589,8 +715,8 @@ describe AutoForme do
|
|
589
715
|
click_link 'Show'
|
590
716
|
select 'Album1'
|
591
717
|
click_button 'Show'
|
592
|
-
page.html.must_match
|
593
|
-
page.html.must_match
|
718
|
+
page.html.must_match(/Name.+Album1b/m)
|
719
|
+
page.html.must_match(/Artist.+Artist2/m)
|
594
720
|
|
595
721
|
click_link 'Search'
|
596
722
|
fill_in 'Name', :with=>'1b'
|