mirror of
https://github.com/discourse/discourse.git
synced 2024-11-27 09:03:44 +08:00
FIX: Upsert a custom field if a unique constraint fails
This commit is contained in:
parent
c78634284c
commit
72bac61c90
|
@ -240,10 +240,7 @@ module HasCustomFields
|
|||
if v.is_a?(Array) && field_type != :json
|
||||
v.each { |subv| _custom_fields.create!(name: k, value: subv) }
|
||||
else
|
||||
_custom_fields.create!(
|
||||
name: k,
|
||||
value: v.is_a?(Hash) || field_type == :json ? v.to_json : v
|
||||
)
|
||||
create_singular(k, v, field_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -252,7 +249,16 @@ module HasCustomFields
|
|||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def create_singular(name, value, field_type = nil)
|
||||
write_value = value.is_a?(Hash) || field_type == :json ? value.to_json : value
|
||||
_custom_fields.create!(name: name, value: write_value)
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
# We support unique indexes on certain fields. In the event two concurrenct processes attempt to
|
||||
# update the same custom field we should catch the error and perform an update instead.
|
||||
_custom_fields.where(name: name).update_all(value: write_value)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def refresh_custom_fields_from_db
|
||||
target = Hash.new
|
||||
|
|
|
@ -8,6 +8,10 @@ describe HasCustomFields do
|
|||
before do
|
||||
DB.exec("create temporary table custom_fields_test_items(id SERIAL primary key)")
|
||||
DB.exec("create temporary table custom_fields_test_item_custom_fields(id SERIAL primary key, custom_fields_test_item_id int, name varchar(256) not null, value text)")
|
||||
DB.exec(<<~SQL)
|
||||
CREATE UNIQUE INDEX ON custom_fields_test_item_custom_fields (custom_fields_test_item_id)
|
||||
WHERE NAME = 'rare'
|
||||
SQL
|
||||
|
||||
class CustomFieldsTestItem < ActiveRecord::Base
|
||||
include HasCustomFields
|
||||
|
@ -28,7 +32,7 @@ describe HasCustomFields do
|
|||
Object.send(:remove_const, :CustomFieldsTestItemCustomField)
|
||||
end
|
||||
|
||||
it "simple modification of custom fields" do
|
||||
it "allows simple modification of custom fields" do
|
||||
test_item = CustomFieldsTestItem.new
|
||||
|
||||
expect(test_item.custom_fields["a"]).to eq(nil)
|
||||
|
@ -67,7 +71,7 @@ describe HasCustomFields do
|
|||
expect(test_item.custom_fields["a"]).to eq("0")
|
||||
end
|
||||
|
||||
it "reload loads from database" do
|
||||
it "reloads from the database" do
|
||||
test_item = CustomFieldsTestItem.new
|
||||
test_item.custom_fields["a"] = 0
|
||||
|
||||
|
@ -87,7 +91,7 @@ describe HasCustomFields do
|
|||
expect(test_item.custom_fields["a"]).to eq("1")
|
||||
end
|
||||
|
||||
it "double save actually saves" do
|
||||
it "actually saves on double save" do
|
||||
test_item = CustomFieldsTestItem.new
|
||||
test_item.custom_fields = { "a" => "b" }
|
||||
test_item.save
|
||||
|
@ -165,7 +169,7 @@ describe HasCustomFields do
|
|||
expect((before_ids - after_ids).size).to eq(1)
|
||||
end
|
||||
|
||||
it "simple modifications don't interfere" do
|
||||
it "doesn't allow simple modifications to interfere" do
|
||||
test_item = CustomFieldsTestItem.new
|
||||
|
||||
expect(test_item.custom_fields["a"]).to eq(nil)
|
||||
|
@ -214,7 +218,6 @@ describe HasCustomFields do
|
|||
end
|
||||
|
||||
it "will not fail to load custom fields if json is corrupt" do
|
||||
|
||||
field_type = "bad_json"
|
||||
CustomFieldsTestItem.register_custom_field_type(field_type, :json)
|
||||
|
||||
|
@ -268,6 +271,23 @@ describe HasCustomFields do
|
|||
expect(test_item.reload.custom_fields).to eq(expected)
|
||||
end
|
||||
|
||||
describe "create_singular" do
|
||||
it "creates new records" do
|
||||
item = CustomFieldsTestItem.create!
|
||||
item.create_singular('hello', 'world')
|
||||
expect(item.reload.custom_fields['hello']).to eq('world')
|
||||
end
|
||||
|
||||
it "upserts on a database constraint error" do
|
||||
item0 = CustomFieldsTestItem.new
|
||||
item0.custom_fields = { "rare" => "gem" }
|
||||
item0.save
|
||||
|
||||
item0.create_singular('rare', "diamond")
|
||||
expect(item0.reload.custom_fields['rare']).to eq("diamond")
|
||||
end
|
||||
end
|
||||
|
||||
describe "upsert_custom_fields" do
|
||||
it 'upserts records' do
|
||||
test_item = CustomFieldsTestItem.create
|
||||
|
|
Loading…
Reference in New Issue
Block a user