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 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'