Skip to content

Commit

Permalink
Ignore unique constraint violations when adding associated objects in…
Browse files Browse the repository at this point in the history
… mtm_update

These can happen if the user clicks back after an update and then
resubmits the form (and certainly other cases). Add a similar test
that removing already removed associated objects also does not
raise an error.
  • Loading branch information
jeremyevans committed May 27, 2021
1 parent eb1e2e3 commit f4f7d19
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
=== master

* Ignore unique constraint violations when adding associated objects in mtm_update (jeremyevans)

* Handle search fields that cannot be typecast correctly by returning no results (jeremyevans)

=== 1.9.1 (2019-07-22)
Expand Down
6 changes: 5 additions & 1 deletion lib/autoforme/models/sequel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,11 @@ def mtm_update(request, assoc, obj, add, remove)
ids.each do |id|
next if id.to_s.empty?
ret = assoc_class ? assoc_class.with_pk(:association, request, id) : obj.send(:_apply_association_options, ref, ref.associated_class.dataset.clone).with_pk!(id)
obj.send(meth, ret)
begin
model.db.transaction(:savepoint=>true){obj.send(meth, ret)}
rescue S::UniqueConstraintViolation
# Already added, safe to ignore
end
end
end
end
Expand Down
64 changes: 64 additions & 0 deletions spec/mtm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,67 @@ def req.xhr?; action_type == 'mtm_update' end
page.all('select')[1].all('option').map{|s| s.text}.must_equal ["Album2", "Album3"]
end
end

describe AutoForme do
before(:all) do
db_setup(:artists=>[[:name, :string]], :albums=>[[:name, :string]], :albums_artists=>proc{column :album_id, :integer, :table=>:albums; column :artist_id, :integer, :table=>:artists; primary_key [:album_id, :artist_id]})
model_setup(:Artist=>[:artists, [[:many_to_many, :albums]]], :Album=>[:albums, [[:many_to_many, :artists]]])
end
after(:all) do
Object.send(:remove_const, :Album)
Object.send(:remove_const, :Artist)
end

it "should handle unique constraint violation errors when adding associated objects" do
app_setup do
model Artist do
mtm_associations :albums
end
model Album
end

artist = Artist.create(:name=>'Artist1')
album = Album.create(:name=>'Album1')

visit("/Artist/mtm_edit")
page.title.must_equal 'Artist - Many To Many Edit'
select("Artist1")
click_button "Edit"

find('h2').text.must_equal 'Edit Albums for Artist1'
page.all('select')[0].all('option').map{|s| s.text}.must_equal ["Album1"]
page.all('select')[1].all('option').map{|s| s.text}.must_equal []
select("Album1", :from=>"Associate With")
artist.add_album(album)
click_button "Update"
page.html.must_include 'Updated albums association for Artist'
Artist.first.albums.map{|x| x.name}.must_equal %w'Album1'
end

it "should handle unique constraint violation errors when adding associated objects" do
app_setup do
model Artist do
mtm_associations :albums
end
model Album
end

artist = Artist.create(:name=>'Artist1')
album = Album.create(:name=>'Album1')
artist.add_album(album)

visit("/Artist/mtm_edit")
page.title.must_equal 'Artist - Many To Many Edit'
select("Artist1")
click_button "Edit"

find('h2').text.must_equal 'Edit Albums for Artist1'
page.all('select')[0].all('option').map{|s| s.text}.must_equal []
page.all('select')[1].all('option').map{|s| s.text}.must_equal ["Album1"]
select("Album1", :from=>"Disassociate From")
artist.remove_album(album)
click_button "Update"
page.html.must_include 'Updated albums association for Artist'
Artist.first.albums.map{|x| x.name}.must_equal []
end
end

0 comments on commit f4f7d19

Please sign in to comment.