ДА вы можете!
У меня был тот же вопрос и я исследовал документы.Способность решить этот вопрос на самом деле очень связана с типом вашей базы данных.
Oracle и Postgresql действительно имеют полезные функции, чтобы легко решить эту проблему.Для MySQL (oracle) или SkySQL (с открытым исходным кодом) это кажется более сложным (но все же возможным).Я бы порекомендовал вам избегать использования этих (MySQL / SkySQL) баз данных, если вам нужны расширенные инструменты для работы с базами данных.
Сначала вы должны постараться как можно больше избегать этой ситуации при разработке приложения , так какопасно играть с идентификаторами, прежде чем они будут сохранены.
Может возникнуть ситуация, когда у вас нет другого выбора: например, когда две таблицы ссылаются на себя и по соображениям безопасности вы не разрешаете УДАЛИТЬили ОБНОВЛЕНИЕ этих таблиц.
В этом случае вы можете использовать базу данных (PostgreSQL, Oracle) nextval для генерации следующего идентификационного номера без фактическоговставка новой записи.
Используйте ее вместе с find_by_sql методом rails.
Чтобы сделать это, например, с postgreSQL и Rails, выберите одну из ваших моделей rails идобавить метод класса (не метод экземпляра!).Это возможно с помощью слова " self " в начале имени метода. self сообщает Ruby, что этот метод может использоваться только классом, а не переменными его экземпляра (объектами, созданными с помощью 'new').
Модель My Rails:
class MyToy < ActiveRecord::Base
...
def self.my_next_id_sequence
self.find_by_sql "SELECT nextval('my_toys_id_seq') AS my_next_id"
end
end
Когда вы генерируете таблицу с миграцией Rails, по умолчанию Rails автоматически создает столбец с именем id и устанавливает его как таблицу первичного ключа .Чтобы гарантировать, что вы не получите никакой « повторяющейся ошибки первичного ключа », Rails автоматически создает sequence внутри базы данных и применяет ее к столбцу id .Для каждой новой записи (строки), которую вы вставляете в вашу таблицу, база данных сама рассчитает, каким будет следующий идентификатор вашей новой записи.
Rails присваивает этой последовательности имя автоматически с именем таблицы , добавляемой с"_id_seq" .Следующую функцию PostgreSQL необходимо применить к этой последовательности, как объяснено здесь .
Теперь о find_by_sql , как объяснено здесь , оно создаст массив , содержащий новые экземпляры объектов вашего класса.Каждый из этих объектов будет содержать все столбцы, которые генерирует оператор SQL.Эти столбцы будут появляться в каждом новом экземпляре объекта в форме атрибутов. Даже если эти атрибуты не существуют в модели вашего класса !
Как вы правильно поняли, наша функция nextval будет возвращать только одно значение.Поэтому find_by_sql создаст массив , содержащий единственный экземпляр объекта с одним атрибутом .Чтобы упростить чтение значения этого самого атрибута, мы назовем результирующий столбец SQL "my_next_id", поэтому наш атрибут будет иметь то же имя.
Вот и все.Мы можем использовать наш новый метод:
my_resulting_array = MyToy.my_next_id_sequence
my_toy_object = my_resulting_array[0]
my_next_id_value = my_toy_object.my_next_id
И использовать его для решения нашей ситуации мертвой блокировки:
my_dog = DogModel.create(:name => 'Dogy', :toy_id => my_next_id_value)
a_dog_toy = MyToy.new(:my_dog_id => my_dog.id)
a_dog_toy.id = my_next_id_value
a_dog_toy.save
Помните, что , если вы не используетеваш my_next_id_value этот идентификатор будет потерян навсегда.(Я имею в виду, что в будущем она не будет использоваться ни одной записью).
База данных не ждет, когда вы ее используете.Если где-то в какое-то время вашему приложению нужно вставить новую запись в ваш my_table_example (может быть, в то же время, когда мы играем с my_next_id_sequence), база данных всегда будет присваивать идентификационный номер этой новой записи сразу после той, которую вы создали с помощьюmy_next_id_sequence, учитывая, что ваше my_next_id_value зарезервировано.Это может привести к ситуациям, когда записи в вашем my_table_example не будут отсортированы по времени их создания.