ОШИБКА: идентификатор с разделителями с нулевой длиной на уровне или рядом с "" "" LINE 1: DELETE FROM "region" WHERE "regions". "" = $ 1

Я использую Rails 4.1 и Postgresql (с жемчужиной PG) в качестве моей базы данных. У меня очень много ассоциаций от компаний до провинций с таблицей объединений, называемой регионами. Теперь, очевидно, таблица регионов не имеет первичной причины, по которой я использовал {: id => false}. Но когда я пытаюсь использовать зависящий от уничтожения или просто просто вызываю уничтожить объект области, я сам получаю эту ошибку:

 ERROR:  zero-length delimited identifier at or near """"
 LINE 1: DELETE FROM "regions" WHERE "regions"."" = $1

Я знаю, что проблема вызвана отсутствием первичного ключа для таблицы регионов. И как ни странно, если я добавлю первичный ключ обратно в таблицу, то разрушение будет прекрасным и без ошибок. Однако, если я удалю первичный ключ из таблицы, ошибка вернется. Я знаю, что это имеет какое-то отношение к postgres, но я не знаю, как это решить, не добавляя столбец первичного ключа в таблицу моих регионов.

Вот фактический запрос

[DEBUG] [AdminUser Load (0.4ms)  SELECT  "admin_users".* FROM "admin_users"  WHERE "admin_users"."id" = 1  ORDER BY "admin_users"."id" ASC LIMIT 1] (pid:29655)
[DEBUG] [Province Load (0.2ms)  SELECT  "provinces".* FROM "provinces"  WHERE "provinces"."id" = $1 LIMIT 1  [["id", 5]]] (pid:29655)
[DEBUG] [ (0.1ms)  BEGIN] (pid:29655)
[DEBUG] [Region Load (0.3ms)  SELECT "regions".* FROM "regions"  WHERE "regions"."province_id" = $1  [["province_id", 5]]] (pid:29655)
[ERROR] [PG::SyntaxError: ERROR:  zero-length delimited identifier at or near """"
LINE 1: DELETE FROM "regions" WHERE "regions"."" = $1

Ответ 1

Вам нужны одинарные кавычки, а не двойные кавычки вокруг пустых строк, двойные кавычки - идентификаторы с разделителями, а "" не является значимым идентификатором ".

пытаться:

WHERE 'regions'.'' = $1

или по крайней мере:

WHERE "regions".'' = $1

Ответ 2

Попробуйте установить dependent: :delete_all.

Пример (не совсем уверен, как вы установили настройку "многие-ко-многим").

# models/region.rb
...
has_many: provinces_regions, depend:: delete_all
has_many: провинции, через:: provinces_regions
...

: destroy/: destroy_all удалит связанные объекты, вызвав их метод destroy, и, таким образом, обратные вызовы (: before_destroy,: after_destroy и т.д.).

: delete/: delete_all удаляет связанные объекты без вызова метода destroy.

Ответ 3

Поскольку ни один из ответов здесь не работал для меня, я думал, что включу мое собственное исправление. Не уверен, что такое перевод для вашего случая использования, но я надеюсь, что суть моей стратегии ясна.

Я тоже использую настраиваемый первичный ключ (uuid). Чтобы удалить запись в моей таблице соединений, я пропустил активную запись для фактического вызова на удаление и вместо этого использовал SQL.

uid = BucketListPhoto.find_by(bucket_list_id: 12, photo_id: 4).uid

deleted_uids = ActiveRecord::Base.connection.execute(
    "DELETE FROM bucket_list_photos WHERE uid='#{uid}' RETURNING uid"
).to_a.map { |record| record['uid'] }

Я переписал BucketListPhoto#destroy чтобы использовать это.

Я попытался перезаписать BuckerListPhoto::ActiveRecord::Query#destroy_all но не смог успешно передать массив uids (чтобы удалить много с одним запросом).

Ответ 4

На основании ответа Алекса Кэрола, но совершенно другого решения.

Если кто-то сделал:

# models/region.rb
...
has_many :provinces_regions, dependent: :destroy_all
has_many :provinces, through: :provinces_regions
...

и получаю эту проблему, тогда я думаю, вы, вероятно, сделали это:

create_table :provinces_regions, id: false do |t|
  t.belongs_to :regions, index: true
  t.belongs_to :provinces, index: true
end

Если приведенное выше верно, то Rails пытается использовать id для запуска обратных вызовов перед уничтожением. Итак, дайте ему id:

create_table :provinces_regions do |t|
  t.belongs_to :regions, index: true
  t.belongs_to :provinces, index: true
end

И, таким образом, вы можете продолжать использовать dependent: :destroy_all и использовать обратные вызовы и другие функции, для которых требуется id.