Zastrzeżenie: ten post jest głównie przypomnieniem dla siebie, więc nie muszę go za każdym razem wygooglować.
w mojej pracy czasami muszę kopiować rekordy bazy danych,wiem, że rails ma co najmniej 2 (jeśli wiesz więcej, daj mi znać!) wbudowane metody robienia tego, ale jeden robi tostopnie inaczej niż drugi. Dwie metody, o których mówię to clone
i dup
.
źródło Rails mówi o obu:
Klon
identyczny z metodą klonowania Ruby. To jest” płytka ” Kopia. Pamiętaj, że twoje atrybuty nie są kopiowane.Oznacza to, że modyfikowanie atrybutów klonu spowoduje modyfikację oryginału, ponieważ oba będą wskazywać na te same atrybuty hash. Jeśli potrzebujesz kopii skrótu atrybutów, użyj metody # dup .
Dup
Duped obiekty nie mają przypisanego id i są traktowane jako nowe rekordy. Nie jest to” płytka ” Kopia, ponieważ kopiuje tylko atrybuty obiektu, a nie jego skojarzenia. Zakres „głębokiej” kopii jest specyficzny dla aplikacji i dlatego pozostaje w gestii aplikacji w celu wdrożenia zgodnie z jej potrzebami.Metoda dup nie zachowuje znaczników czasu(created|updated)_(at|on).
OK, to jasne. Ale co to dokładnie oznacza w praktyce? Stwórz próbkę kodu:
p1 = Post.create(title: 'Post 1', message: 'Amazing message')=> #<Post id: 1, title: "Post 1", message: "Amazing message", created_at: "2014-07-01 19:45:44", updated_at: "2014-07-01 19:45:44">p2 = p1.clone=> #<Post id: 1, title: "Post 1", message: "Amazing message", created_at: "2014-07-01 19:45:44", updated_at: "2014-07-01 19:45:44">p3 = p1.dup=> #<Post id: nil, title: "Post 1", message: "Amazing message", created_at: nil, updated_at: nil>
jak widać, gdy clone
obiekt DB, zachowuje wszystkie swoje dane, nawet id, a gdy używasz dup
tworzy nowy obiekt, z danymi starego obiektu. Id oraz createdat i updatedat są jednak puste!
weźmy powyższy przykład kodu nieco dalej, co się stanie, jeśli zmienimy dane
najpierw Clone
p1 = Post.create(title: 'Post 1', message: 'Amazing message')p2 = p1.clonep2.title = "This is now p2"p1 #=> #<Post id: 1, title: "This is now P2", message: "Amazing message", created_at: "2014-07-01 19:45:44", updated_at: "2014-07-01 19:45:44">p2 #=> #<Post id: 1, title: "This is now P2", message: "Amazing message", created_at: "2014-07-01 19:45:44", updated_at: "2014-07-01 19:45:44">
jak widać, kiedy zmieniam p2
dane w p1
również są zmieniane. Dzieje się tak, ponieważ clone
tworzy tylko płytką kopię.
teraz spójrzmy na Dup
p1 = Post.create(title: 'Post 1', message: 'Amazing message')p3 = p1.clonep3.title = "This is now p3"p1 #=> #<Post id: 1, title: "Post 1", message: "Amazing message", created_at: "2014-07-01 19:45:44", updated_at: "2014-07-01 19:45:44">p3 #=> #<Post id: nil, title: "This is now P3", message: "Amazing message", created_at: nil, updated_at: nil>
obiekt p3
ma wpływ tylko na naszą zmianę, dzieje się tak dlatego, że jest to nowy obiekt, jeśli zapytasz persisted?
, zwróci false
, ponieważ nie jest jeszcze przechowywany w bazie danych. Więc jeśli chcemy zapisać p3
musimy zadzwonić save
.
czy to również oznacza, że jeśli użyję clone
, że obiekty są dokładnie takie same? Sprawdźmy to!
p1 = Post.create(title: 'Post 1', message: 'Amazing message')p2 = p1.clonep3 = p1.dupp2 == p1 #=> truep3 == p1 #=> false
możemy więc stwierdzić, że metoda clone
wykonuje płytką kopię, a dup
tworzy nowy obiekt. Mała uwaga, dup
nie kopiuje skojarzeń