Yes, you can!
I had the same question and examined the documents. The ability to resolve this issue is very similar to your database type.
Oracle and Postgresql have useful features to easily solve this problem. For MySQL (oracle) or SkySQL (open-source), this seems more complicated (but still possible). I would recommend that you avoid using these (MySQL / SkySQL) databases if you need advanced database tools.
First, you should try to avoid this situation as much as possible in the design of your application , since it is dangerous to play with identifiers before they are saved.
There may be a situation where you have no other choice: For example, when two tables refer to themselves and for security reasons you do not allow DELETE or UPDATE in these tables.
If so, you can use (postgreSQL, Oracle) nextval database to generate the next ID number without actually inserting a new record.
Use it in conjunction with the find_by_sql method.
To do this using postgreSQL and Rails, for example, select one of your rail models and add a class method (rather than an instance method!). This is possible using the word " self " at the beginning of the method name. self tells Ruby that this method is used only by the class and not by its instance variables (objects created using "new").
My Rails Model:
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
When creating a table with Rails migration by default, Rails automatically creates a column called id and sets it as the primary key table. To make sure that you are not getting a “duplicate primary key error”, Rails automatically creates a sequence inside the database and applies it to the id column. For each new record (row) that you insert into your table, the database will calculate by itself what will be the next identifier for your new record.
The rails automatically record this sequence with the table name with the addition of "_id_seq" . The following postgreSQL sequence should apply to this sequence as described here .
Now about find_by_sql , as described here , it will create an array containing instances of the new objects of your class. Each of these objects will contain all the columns created by the SQL statement. These columns will appear in each instance of the new object as attributes. Even if these attributes do not exist in your class model !
As you reasonably understood, our next function returns only one value. Thus, find_by_sql will create an array containing an instance of one object with a single attribute . To make it easier to read the value of this attribute itself, we will call the resulting SQL column "my_next_id", so our attribute will have the same name.
So what is it. We can use our new method:
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
And use it to solve our deadlock situation:
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
Remember that if you do not use your my_next_id_value, this identification number will be lost forever. (I mean that it will not be used by any entry in the future).
The database does not wait when you use it. If somewhere at any time your application should insert a new record in its my_table_example file (possibly simultaneously with the game with my_next_id_sequence), the database will always assign the identifier number of this new record immediately after the one you created using my_next_id_sequence, considering that your my_next_id_value is reserved. This can lead to situations where the entries in your my_table_example file are not sorted by the time they were created.