autoforme 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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'
|