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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 299ca55f54b46bf0629229262853d3dc19a5bc64
4
- data.tar.gz: c136195e2191c628c71b0e66e8dad48db965ac37
3
+ metadata.gz: 7431cd2d4051bea42ed58879c0d0418de7282b5d
4
+ data.tar.gz: f8d7d4c14152aef6efeedd2fb763df6cd3d4e77d
5
5
  SHA512:
6
- metadata.gz: 0fe74271b2d60e2269041d3c8c17300538d043eb5901d97e4c73936a088c8f9d9524c9c09419edac647188eb3ffecc6b2fee1b91ccf05516694e43c16c0ebdb7
7
- data.tar.gz: f4680d5384dfa5984579f4d7022b956d1e0d6c077b3069de0543b5a8d4260d0bb23e662839f7992f434cd2542cb8ce3766cc8cc32c2d0d94203424071996a2d9
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} -rubygems -I lib -e 'ARGV.each{|f| require f}' ./spec/*_spec.rb"
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 framework: #{type.inspect}"
30
+ raise Error, "unsupported #{map_type}: #{type.inspect}"
31
31
  end
32
32
  end
33
33
  klass
@@ -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
- @type = request.action_type.to_sym
60
- @normalized_type = NORMALIZED_ACTION_MAP.fetch(@type, @type)
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 |f|
323
- f.button(:value=>'Edit', :class=>'btn btn-primary')
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 |f|
328
- f.button(:value=>'Delete', :class=>'btn btn-danger')
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 id = request.id
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 add = request.params['add']
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 |assoc_obj|
596
+ assoc_objs.each do |assoc_obj1|
603
597
  t << "<li>"
604
- t << association_link(mc, assoc_obj)
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 :text=>@autoforme_text
57
+ render :body=>@autoforme_text
58
58
  elsif @autoforme_action.request.xhr?
59
- render :text=>@autoforme_text
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 :text=>'Unhandled Request', :status=>404
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 *current_matchers do
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
@@ -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, opts={})
323
- case nm = opts[:name_method]
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 reable string for the associated object.
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{|ds, opts| ds.where(S.ilike(display, "%#{ds.escape_like(query)}%"))}
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)
@@ -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
- # Any options for the table
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|
@@ -2,7 +2,7 @@
2
2
 
3
3
  module AutoForme
4
4
  # Version constant, use <tt>AutoForme.version</tt> instead.
5
- VERSION = '1.4.0'.freeze
5
+ VERSION = '1.5.0'.freeze
6
6
 
7
7
  # Returns the version as a frozen string (e.g. '0.1.0')
8
8
  def self.version
data/spec/all.rb ADDED
@@ -0,0 +1,2 @@
1
+ puts "Running specs with #{ENV['FRAMEWORK']||'roda'} framework"
2
+ Dir['./spec/*_spec.rb'].each{|f| require f}
@@ -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 /Name.+Album1b/m
42
- page.html.must_match /Artist.+Artist2/m
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 /Name.+Album1/m
113
- page.html.must_match /Artist.+A1A1/m
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 /Name.+Album1/m
156
- page.html.must_match /Artist.+A1A1/m
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 /Name.+Album1/m
200
- page.html.must_match /Artist.+A1/m
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 /Name.+X/m
278
- page.html.must_match /Artist.+B/m
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 /Name.+D/m
344
- page.html.must_match /Artist.+Y 2/m
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.must_match /Album1/
451
- page.html.wont_match />edit</
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.wont_match /create/
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 /Name.+Album1b/m
549
- page.html.must_match /Artist.+Artist2/m
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 /Name.+Album1b/m
593
- page.html.must_match /Artist.+Artist2/m
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'