Tworzę nowy rekord w ten sposób:
truck = Truck.create(:name=>name, :user_id=>2)
Moja baza danych zawiera obecnie kilka tysięcy podmiotów dla ciężarówki, ale przypisałem identyfikatory do kilku z nich w sposób, który pozostawił dostępne identyfikatory. Więc co się dzieje, to rails tworzy element o id = 150 i działa dobrze. Ale potem próbuje utworzyć element i przypisać mu id = 151, ale ten identyfikator może już istnieć, więc widzę ten błąd:
ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint "companies_pkey"
DETAIL: Key (id)=(151) already exists.
Następnym razem, gdy uruchomię tę akcję, po prostu przypisze identyfikator 152, który będzie działał dobrze, jeśli ta wartość nie jest już pobrana. Jak mogę sprawić, by railsy sprawdzały, czy identyfikator już istnieje, zanim go przypisuje?
Dzięki!
EDYTOWAĆ
Duplikuje się identyfikator ciężarówki. Użytkownik już istnieje i jest w tym przypadku stałą. W rzeczywistości jest to problem, z którym muszę się uporać. Jedną z opcji jest ponowne utworzenie tabeli przy pomocy niech rails auto przypisuje tym razem każdy identyfikator. Zaczynam myśleć, że to może być najlepszy wybór, ponieważ mam kilka innych problemów, ale migracja w tym celu byłaby bardzo skomplikowana, ponieważ ciężarówka jest kluczem obcym w wielu innych tabelach. Czy istniałby prosty sposób, aby szyny tworzyły nową tabelę z tymi samymi danymi, które są już zapisane w ciężarówce, z automatycznie przypisywanymi identyfikatorami i zachowując wszystkie istniejące relacje?
Odpowiedzi:
Railsy prawdopodobnie używają wbudowanej sekwencji PostgreSQL. Idea sekwencji polega na tym, że jest ona używana tylko raz.
Najprostszym rozwiązaniem jest ustawienie kolejności dla kolumny company.id na najwyższą wartość w tabeli za pomocą zapytania takiego:
SELECT setval('company_id_seq', (SELECT max(id) FROM company));
Zgaduję, że nazwa Twojej sekwencji „company_id_seq”, nazwa tabeli „company” i nazwa kolumny „id”… proszę zastąpić je poprawnymi. Możesz pobrać nazwę sekwencji za pomocą
SELECT pg_get_serial_sequence('tablename', 'columname');
lub spojrzeć na definicję tabeli za pomocą\d tablename
.Alternatywnym rozwiązaniem jest zastąpienie metody save () w klasie firmy, aby ręcznie ustawić identyfikator firmy dla nowych wierszy przed zapisaniem.
źródło
create table t (id serial not null primary key); insert into t values (1); insert into t values (default); ERROR: duplicate key value violates unique constraint "t_pkey" DETAIL: Key (id)=(1) already exists.
Zrobiłem to, co rozwiązało problem.
ActiveRecord::Base.connection.tables.each do |t| ActiveRecord::Base.connection.reset_pk_sequence!(t) end
Znalazłem reset_pk_sequence! z tego wątku. http://www.ruby-forum.com/topic/64428
źródło
ActiveRecord::Base.connection.tables.each { |t| ActiveRecord::Base.connection.reset_pk_sequence!(t) }
Na podstawie odpowiedzi @Apie .
Możesz wykonać zadanie i uruchomić je, kiedy potrzebujesz:
rake database:correction_seq_id
Tworzysz takie zadania:
A w wygenerowanym pliku (
lib/tasks/database.rake
) umieść:namespace :database do desc "Correction of sequences id" task correction_seq_id: :environment do ActiveRecord::Base.connection.tables.each do |t| ActiveRecord::Base.connection.reset_pk_sequence!(t) end end end
źródło
Brzmi to jak problem z bazą danych, a nie z Railsami. Czy jest możliwe, że Twoja baza danych zawiera nieprawidłowe ziarno tożsamości w
id
kolumnie? Aby przetestować, spróbuj wykonać kilka operacji wstawiania bezpośrednio do bazy danych i sprawdź, czy istnieje takie samo zachowanie.źródło
Rozwiązałem ten problem, wykonując polecenie.
Uruchom to w konsoli railsów
ActiveRecord::Base.connection.reset_pk_sequence!('table_name')
źródło