Как исправить SQLite3 :: ConstraintException: ограничение UNIQUE не удалось: - PullRequest
0 голосов
/ 05 октября 2019

Я добавляю несколько гостей в список гостей, импортируя электронную таблицу Excel.

Изначально это был отдельный ресурс, и все работало отлично. Мне удалось импортировать новый список гостей, а также повторно импортировать обновленный список гостей.

Теперь я вложил модель своего списка гостей в свою модель событий, чтобы событие имело много списков гостей, а список гостей принадлежал событию, и яТеперь при импорте электронной таблицы появляется ошибка с ограничениями.

Насколько я знаю, я внес корректные изменения в мои файлы для вложения, а также сбросил базу данных и запустил db: migrate. Первый импорт работал, но затем выдает ошибку при повторном импорте того же файла (это работало на оригинальном)

Старый контроллер:

 def import
    Guestlist.import(params[:file])
    redirect_to guestlists_path, notice: "Guest-list 
  Successfully Imported."
   end

Новый контроллер:

 def import
  @guestlists = @event.guestlists.import(params[:file])
  redirect_to event_guestlists_path(@event), notice: "Guest-list Successfully Imported."
end

Метод импорта:

def self.import(file)
  spreadsheet = Roo::Spreadsheet.open(file.path)
  header = spreadsheet.row(1)
  (2..spreadsheet.last_row).each do |i|
    row = Hash[[header, spreadsheet.row(i)].transpose]
    guestlist = find_by(id: row["id"]) || new
    guestlist.attributes = row.to_hash
    guestlist.save!
  end
end

Метод сохранения:

def save
    if imported_items.map(&:valid?).all?
      imported_items.each(&:save!)
      true
    else
      imported_items.each_with_index do |item, index|
        item.errors.full_messages.each do |msg|
          errors.add :base, "Row #{index + 1}: #{msg}"
        end
      end
      false
    end
  end

Схема гостевого списка:

  create_table "guestlists", force: :cascade do |t|
    t.string "firstname"
    t.string "email"
    t.string "response"
    t.integer "event_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "dietary_requirements"
    t.string "lastname"
    t.index ["event_id"], name: "index_guestlists_on_event_id"
  end

Если потребуется еще какой-либо код, я добавлю соответственно!

Заранее спасибо

Журнал ошибок с терминала:

ActiveRecord::RecordNotUnique (SQLite3::ConstraintException: UNIQUE constraint failed: guestlists.id: INSERT INTO "guestlists" ("id", "firstname", "email", "created_at", "updated_at", "lastname") VALUES (?, ?, ?, ?, ?, ?)):

app/models/guestlist.rb:20:in `block in import'
app/models/guestlist.rb:16:in `import'
app/controllers/guestlists_controller.rb:34:in `import'
Started POST "/events/1/guestlists/import" for ::1 at 2019-10-05 13:19:03 +0200
Processing by GuestlistsController#import as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"UmBvaiHr3s2HJ4WKxBazfRNtVT1E5BLrejPjLhx1IbrlGshEbE8UcaQIilJJeq2m3rGefDtJ65C0iRToZWvOqA==", "file"=>#<ActionDispatch::Http::UploadedFile:0x007fe42d188080 @tempfile=#<Tempfile:/var/folders/sw/t3c38b_d0z343xcp6sznp_h80000gn/T/RackMultipart20191005-44877-kiw9l6.xls>, @original_filename="guestlists (7).xls", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"file\"; filename=\"guestlists (7).xls\"\r\nContent-Type: application/octet-stream\r\n">, "commit"=>"Import Guest List", "event_id"=>"1"}
  User Load (2.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ /Users/ryan/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/activerecord-5.2.2.1/lib/active_record/log_subscriber.rb:98
  Event Load (2.3ms)  SELECT  "events".* FROM "events" WHERE "events"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/guestlists_controller.rb:111
  Guestlist Load (2.6ms)  SELECT  "guestlists".* FROM "guestlists" WHERE "guestlists"."event_id" = ? AND "guestlists"."id" = ? LIMIT ?  [["event_id", 1], ["id", 1], ["LIMIT", 1]]
  ↳ app/models/guestlist.rb:18
   (0.2ms)  begin transaction
  ↳ app/models/guestlist.rb:20
  Guestlist Create (1.0ms)  INSERT INTO "guestlists" ("id", "firstname", "email", "created_at", "updated_at", "lastname") VALUES (?, ?, ?, ?, ?, ?)  [["id", 1], ["firstname", "ryan"], ["email", "ryan.neill11@gmail.com"], ["created_at", "2019-10-05 11:19:04.522415"], ["updated_at", "2019-10-05 11:19:04.522415"], ["lastname", "neill"]]
  ↳ app/models/guestlist.rb:20
   (0.1ms)  rollback transaction
  ↳ app/models/guestlist.rb:20
Completed 500 Internal Server Error in 243ms (ActiveRecord: 12.8ms)

1 Ответ

0 голосов
/ 05 октября 2019

Проблема в том, что теперь вы вызываете import для отношения, которое ограничено определенным событием @event.guestlists.import(params[:file]). В вашем методе импорта он пытается найти запись, подобную этой:

guestlist = find_by(id: row["id"]) || new

Если список гостей не прикреплен к вашему событию, но существует список, прикрепленный к другому событию, он выигрываетне найти его здесь, потому что self в этом контексте относится к вашему отношению @event.guestlists, а не к классу GuestList. Если он существует в другом событии, он все равно попытается создать НОВЫЙ список гостей, используя идентификатор, который уже существует в базе данных.

Вот почему вы получаете нарушение уникальности идентификатора:

ActiveRecord::RecordNotUnique (SQLite3::ConstraintException: UNIQUE constraint failed: guestlists.id

Когда вы ранее вызывали GuestList.import, контекст для import былGuestList class, поэтому find_by в этом контексте означает GuestList.find_by, и ваш список всегда будет найден, и он не будет пытаться создать новый, если он уже существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...