Czy istnieje sposób na zastąpienie wartości identyfikatora modelu podczas tworzenia? Coś jak:
Post.create(:id => 10, :title => 'Test')
byłby idealny, ale oczywiście nie zadziała.
ruby-on-rails
activerecord
Codebeef
źródło
źródło
Odpowiedzi:
id jest po prostu attr_protected, dlatego nie możesz użyć przypisania masowego, aby go ustawić. Jednak przy ręcznym ustawianiu po prostu działa:
Nie jestem pewien, jaka była pierwotna motywacja, ale robię to podczas konwersji modeli ActiveHash do ActiveRecord. ActiveHash pozwala na użycie tej samej semantyki allowed_to w ActiveRecord, ale zamiast migracji i tworzenia tabeli oraz ponoszenia narzutu bazy danych przy każdym wywołaniu, po prostu przechowujesz dane w plikach yml. Klucze obce w bazie danych odwołują się do identyfikatorów w pamięci w pliku yml.
ActiveHash doskonale nadaje się do list wyboru i małych tabel, które zmieniają się rzadko i zmieniają się tylko przez programistów. Więc przechodząc z ActiveHash do ActiveRecord, najłatwiej jest po prostu zachować te same odniesienia do wszystkich kluczy obcych.
źródło
ActiveRecord::VERSION::STRING == "3.2.11"
tutaj (z adapterem sqlite3) i powyższe działa dla mnie.Próbować
to powinno dać ci to, czego szukasz.
źródło
Możesz też użyć czegoś takiego:
Chociaż, jak stwierdzono w dokumentacji , ominie to zabezpieczenia przydziału masowego.
źródło
Dla szyn 4:
Inne odpowiedzi Rails 4 nie działały dla mnie. Wiele z nich pojawiła się do zmian podczas sprawdzania za pomocą konsoli Rails, ale gdy sprawdziłem wartości w bazie danych MySQL, pozostały one na niezmienionym poziomie. Inne odpowiedzi tylko czasami działały.
Przynajmniej w przypadku MySQL przypisanie
id
poniżej numeru identyfikatora automatycznego zwiększania nie działa, chyba że używaszupdate_column
. Na przykład,Jeśli zmienisz
create
nanew
+save
, nadal będziesz mieć ten problem. Ręczna zmianaid
podobnychp.id = 10
również powoduje ten problem.Ogólnie rzecz biorąc, użyłbym
update_column
do zmiany,id
mimo że kosztuje to dodatkowe zapytanie do bazy danych, ponieważ będzie działać przez cały czas. Jest to błąd, który może nie pojawić się w środowisku programistycznym, ale może dyskretnie uszkodzić produkcyjną bazę danych przez cały czas, gdy mówi, że działa.źródło
Post.new.update(id: 10, title: 'Test')
Właściwie okazuje się, że wykonanie następujących czynności:
źródło
validate: false
, zamiast po prostufalse
. Jednak nadal napotykasz problem z atrybutem chronionym - istnieje oddzielny sposób na obejście tego, który przedstawiłem w mojej odpowiedzi.Jak zauważa Jeff, id zachowuje się tak, jakby był attr_protected. Aby temu zapobiec, musisz zastąpić listę domyślnych atrybutów chronionych. Zachowaj ostrożność, robiąc to wszędzie tam, gdzie informacje o atrybutach mogą pochodzić z zewnątrz. Pole id jest domyślnie chronione z jakiegoś powodu.
(Testowane z ActiveRecord 2.3.5)
źródło
możemy zastąpić attribute_protected_by_default
źródło
Nie wydaje mi się to czymś, co normalnie chciałbyś zrobić, ale działa całkiem dobrze, jeśli musisz wypełnić tabelę ustalonym zestawem identyfikatorów (na przykład podczas tworzenia wartości domyślnych za pomocą zadania rake), a ty chcesz zastąpić autoinkrementację (aby za każdym razem, gdy uruchamiasz zadanie, tabela była zapełniana tymi samymi identyfikatorami):
źródło
Umieść tę funkcję create_with_id na początku pliku seeds.rb, a następnie użyj jej do utworzenia obiektu, w którym wymagane są jawne identyfikatory.
i używaj go w ten sposób
zamiast używać
Foo.create({id:1,name:"My Foo",prop:"My other property"})
źródło
W tym przypadku jest podobny problem, który należało nadpisać
id
jakimś rodzajem niestandardowej daty:I wtedy :
Callback działa dobrze.
Powodzenia!.
źródło
id
oparty na Uniksie znacznik czasu. Zrobiłem to w środkubefore_create
. Działa w porządku.W przypadku Rails 3 najprostszym sposobem na to jest użycie
new
zwithout_protection
udoskonaleniem, a następniesave
:W przypadku danych początkowych sensowne może być ominięcie weryfikacji, którą można zrobić w ten sposób:
W rzeczywistości dodaliśmy metodę pomocniczą do ActiveRecord :: Base, która jest deklarowana bezpośrednio przed wykonaniem plików źródłowych:
I teraz:
W Railsach 4 powinieneś używać StrongParams zamiast chronionych atrybutów. W takim przypadku będziesz mógł po prostu przypisać i zapisać bez przekazywania żadnych flag do
new
:źródło
{}
odpowiedzi Samuela powyżej (Rails3).id
jest nadal 10.id
zostało przekazane jako 10 - więc dokładnie tak powinno być. Jeśli nie tego się spodziewałeś, czy możesz wyjaśnić to na przykładzie?W Railsach 4.2.1 z Postgresql 9.5.3
Post.create(:id => 10, :title => 'Test')
działa, o ile nie ma już wiersza z id = 10.źródło
możesz wstawić id przez sql:
źródło