Rieles forma de restablecer la semilla en el campo de identificación

He encontrado las respuestas de "SQL puro" a esta pregunta. ¿Hay alguna manera, en Rails , para restablecer el campo de id para una tabla específica?
¿Por qué quiero hacer esto? Porque tengo tablas con datos en constante movimiento, raramente más de 100 filas, pero siempre diferentes. Es hasta 25k ahora, y simplemente no tiene sentido. Tengo la intención de utilizar un planificador interno a la aplicación Rails (rufus-scheduler) para ejecutar el reinicio del campo de identificación mensualmente.

Salí con una solución basada en la respuesta de hgiménez y esta otra .

Como normalmente trabajo con Sqlite o PostgreSQL, solo desarrollo para esos; pero extenderlo a, digamos MySQL, no debería ser demasiado problemático.

Coloque esto dentro de lib / y solicítelo en un inicializador:

# lib/active_record/add_reset_pk_sequence_to_base.rb module ActiveRecord class Base def self.reset_pk_sequence case ActiveRecord::Base.connection.adapter_name when 'SQLite' new_max = maximum(primary_key) || 0 update_seq_sql = "update sqlite_sequence set seq = #{new_max} where name = '#{table_name}';" ActiveRecord::Base.connection.execute(update_seq_sql) when 'PostgreSQL' ActiveRecord::Base.connection.reset_pk_sequence!(table_name) else raise "Task not implemented for this DB adapter" end end end end 

Uso:

 Client.count # 10 Client.destroy_all Client.reset_pk_sequence Client.create(:name => 'Peter') # this client will have id=1 

EDITAR: Dado que el caso más habitual en el que deseará hacer esto es después de borrar una tabla de database, le recomiendo echar un vistazo a database_cleaner . Maneja el restablecimiento de ID automáticamente. Puedes decirle que elimine solo las tablas seleccionadas como esta:

 DatabaseCleaner.clean_with(:truncation, :only => %w[clients employees]) 

Nunca mencionaste qué DBMS estás usando. Si esto es postgreSQL, el adaptador postgres ActiveRecord tiene un reset_pk_sequences! método que podrías usar:

 ActiveRecord::Base.connection.reset_pk_sequence!('table_name') 

Supongo que no te importan los datos:

 def self.truncate! connection.execute("truncate table #{quoted_table_name}") end 

O si lo hace, pero no demasiado (hay un segmento de time donde los datos solo existen en la memory):

 def self.truncate_preserving_data! data = all.map(&:clone).each{|r| raise "Record would not be able to be saved" unless r.valid? } connection.execute("truncate table #{quoted_table_name}") data.each(&:save) end 

Esto dará nuevos loggings, con los mismos attributes, pero los identificadores comienzan en 1.

Cualquier cosa que belongs_to a esta table podría ser confusa.

Un problema es que este tipo de campos se implementan de forma diferente para diferentes bases de datos: secuencias, autoincrementos, etc.

Siempre puede soltar y volver a agregar la tabla.

No, no hay tal cosa en Rails. Si necesita una buena identificación para mostrar a los usuarios, guárdela en una tabla separada y vuelva a utilizarla.

Solo podría hacer esto en Rails si los _ids están siendo ajustados por Rails. Siempre que su database establezca los _ids, no podrá controlarlos sin utilizar SQL.

Nota al margen: supongo que usar raíles para llamar regularmente a un procedimiento SQL que se restablece o descarta y recrea una secuencia no sería una solución puramente SQL, pero no creo que eso sea lo que estás preguntando …

EDITAR:

Descargo de responsabilidad: no sé mucho sobre los Rails.

Desde la perspectiva de SQL, si tiene una tabla con id first_name last_name columnas primer nombre id first_name last_name y normalmente insert into table (first_name, last_name) values ('bob', 'smith') puede cambiar sus consultas para insert into table (id, first_name, last_name) values ([variable set by rails], 'bob', 'smith') esta forma, _id se establece mediante una variable, en lugar de establecerse automáticamente mediante SQL. En ese punto, los Rails tienen control total sobre lo que son los _ids (aunque si es un PK, necesitas asegurarte de no utilizar el mismo valor mientras todavía está allí).

Si va a dejar la asignación en la database, debe tener los carriles en ejecución (en cualquier horario) algo como:

 DROP SEQUENCE MY_SEQ; CREATE SEQUENCE MY_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 1; 

a la secuencia que controle los identificadores para su table. Esto eliminará la secuencia actual y creará una nueva. Esta es la forma más sencilla que conozco de 'restablecer' una secuencia.

Basado en la respuesta de @hgmnz, hice este método que establecerá la secuencia a cualquier valor que desee … (Solo probado con el adaptador Postgres).

 # change the database sequence to force the next record to have a given id def set_next_id table_name, next_id connection = ActiveRecord::Base.connection def connection.set_next_id table, next_id pk, sequence = pk_and_sequence_for(table) quoted_sequence = quote_table_name(sequence) select_value <<-end_sql, 'SCHEMA' SELECT setval('#{quoted_sequence}', #{next_id}, false) end_sql end connection.set_next_id(table_name, next_id) end 

Rieles para, por ejemplo, MySQL, pero con la pérdida de todos los datos en los users tabla :

 ActiveRecord::Base.connection.execute('TRUNCATE TABLE users;') 

Quizás ayude a alguien;)