przejście z CarrierWave do ActiveStorage w aplikacji Rails

NJ Pearman
NJ Pearman

Obserwuj

Cze 20, 2018 · 9 min czytać

używamy Ruby on Rails do nauczania tworzenia aplikacji internetowych w EPFL Extension School. Jest to świetny framework, który jest solidny, wypróbowany i zaufany i prezentuje łatwą do naśladowania strukturę podczas podejmowania pierwszych kroków nauki o tworzeniu stron internetowych.

ale jest to również stale rozwijające się oprogramowanie, z ulepszeniami i nowymi funkcjami wydawanymi co roku. Jednym z ostatnich dodatków do Rails w wersji 5.2 jest funkcja ActiveStorage, która po raz pierwszy dodaje łatwe zarządzanie przesyłaniem plików do core Rails framework.

w pierwszej iteracji naszego programu do tworzenia aplikacji webowych zamieściliśmy temat, w którym dowiedzieliśmy się, jak dodawać pliki do aplikacji Rails. Używamy jednak Rails 5.1 w programie, A temat przesyłania plików wykorzystuje jedno z powszechnie stosowanych rozwiązań firm trzecich do dodawania przesyłanych plików, zwane CarrierWave. Jest to solidny klejnot firm trzecich, który pozwala nam implementować przesyłanie plików w aplikacji Rails i jest używany w wielu rzeczywistych aplikacjach Ruby on Rails-w tym w naszej platformie edukacyjnej!

ale wraz z wprowadzeniem ActiveStorage, te perełki innych firm stają się mniej atrakcyjne niż to nowe rozwiązanie dołączone do szyn. W rzeczywistości Paperclip, jeden z innych popularnych klejnotów do przesyłania plików innych firm, ogłosił już, że jest przestarzały na rzecz ActiveStorage. Twórcy Paperclip uznali, że ActiveStorage jest lepszym wyborem dla programistów i zaprzestali dalszych prac nad własnym klejnotem.

przyjrzyjmy się więc dokładniej, co trzeba zrobić, aby przejść z CarrierWave w Rails 5.1 do ActiveStorage w Rails 5.2.

aplikacja

w programie do tworzenia aplikacji webowych pracujemy poprzez budowanie aplikacji webowej o nazwie My Bucket List. Jest to aplikacja, która pozwala użytkownikom tworzyć i śledzić doświadczenia, które zawsze chcieli osiągnąć. Użytkownicy mogą zobaczyć, co inni ludzie stworzyli i śledzić je zbyt. Jedna z funkcji w aplikacji pozwala użytkownikowi przesłać własny awatar, a my budujemy tę funkcję, aby dowiedzieć się o przesyłaniu plików i załącznikach za pomocą CarrierWave.

użytkownik może przesłać awatar za pomocą tego formularza, używając CarrierWave

, więc najpierw zróbmy szybki przegląd tego, co wiąże się z dodaniem prostego załącznika za pomocą CarrierWave.

Konfiguracja CarrierWave

aby włączyć CarrierWave do projektu, musimy:

  • Dodaj klejnot CarrierWave do Gemfile.
  • Dołącz Adapter CarrierWave dla ActiveRecord w inicjalizatorze konfiguracji, config/initializers/carrierwave.rb.

a następnie aby dodać załącznik obrazu do modelu, musimy:

  • Wygeneruj Uploader używając rails generate uploader UploaderName.
  • Dodaj atrybut w modelu, aby zapisać dołączoną nazwę pliku dla każdego rekordu, z powiązaną migracją bazy danych.
  • Edytuj wartości w programie przesyłającym, takie jak lokalizacja pamięci i domyślny obraz.
  • użyj makra mount_uploader w modelu, aby włączyć konkretny uploader.
  • Dodaj pole formularza pliku, w którym można przesłać obraz.
  • Dodaj atrybut model do listy silnych parametrów w kontrolerze obsługującym formularz zawierający pole plik.

rozważmy jeszcze jeden z tych punktów: w CarrierWave konieczne jest dodanie określonych atrybutów do każdego modelu, który musi mieć dołączony plik. Na przykład model User, który potrzebuje dołączonego do niego obrazu avatar, będzie potrzebował atrybutu o nazwie :avatar, który jest String. Wymaga to migracji bazy danych, aby dodać podstawową kolumnę bazy danych, a także utworzenia i zamontowania klasy Uploader do tego atrybutu w modelu.

nie jest to szczególnie pracochłonne, ale, jak zobaczymy, ActiveStorage wymaga znacznie mniej kodu w poszczególnych przypadkach.

jeszcze jeden punkt do podkreślenia jest to, że w mojej aplikacji – aplikacji My Bucket List-CarrierWave Avatar uploader jest skonfigurowany z domyślnym prostym przechowywaniem plików. W kolejności słów przesłane obrazy są przechowywane gdzieś wewnątrz folderu public/ w aplikacji. Ta dokładna ścieżka jest zdefiniowana w klasie Uploader dla awatara i jest ustawiona na "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}". Jest to ścieżka względem folderu public/, dzięki czemu przesłane obrazy są bezpośrednio dostępne za pośrednictwem serwera www. Pozwala to na bezpośredni dostęp do plików załączników, które możemy później kontrastować z ActiveStorage.

aktualizacja Rails

przed przejrzeniem activestorage, konieczne jest uaktualnienie do Rails 5.2. Jest to zadanie, które może być bardzo zaangażowane, w zależności od złożoności aplikacji. Aplikacja, której tutaj używam, którą budujemy w naszym programie WAD, nie jest szczególnie trudna do aktualizacji, ale nadal wymaga troski i uwagi.

oto, co zrobiłem, aby zaktualizować aplikację My Bucket List z Rails 5.1 do Rails 5.2.

najpierw utworzyłem nową gałąź w moim repozytorium git, aby wyizolować aktualizację-ważne jest, aby móc wrócić do poprzedniej działającej wersji aplikacji, jeśli coś pójdzie nie tak w procesie aktualizacji!

w nowym branchu zmieniłem wersję Rails w Gemfile z '~> 5.1.2' na '~> 5.2.0', a następnie uruchomiłem bin/bundle update rails — to polecenie pobiera nową wersję rails i wszystkie powiązane gemy w aplikacji. W mojej aplikacji nie było konfliktów klejnotów, ale jeśli używasz klejnotów innych firm, być może będziesz musiał rozwiązać konflikty między różnymi wersjami klejnotów w tym momencie!

po zainstalowaniu nowego klejnotu Rails i jego zależności, konieczna jest aktualizacja samej aplikacji. Zrobiłem to używając bin/bundle exec rails app:update. Polecenie to programowo aktualizuje wszystkie niezbędne pliki w aplikacji do pracy z Rails 5.2.

ale … to polecenie nadpisze zmiany wprowadzone w aplikacji, takie jak config/routes.rb. Na szczęście polecenie pyta, czy nadpisać każdy plik i możliwe jest diff dowolny z tych plików podczas tego procesu, aby sprawdzić, co zostanie nadpisane. Znak zachęty dla każdego nadpisania to , co oznacza:

  • Y dla „tak, Nadpisz mój plik” i jest domyślną opcją, jeśli po prostu naciśniesz Enter.
  • n Dla „Nie, Nie nadpisuj mojego pliku”
  • a dla ” tak, Nadpisz ten plik i Nadpisz każdy inny plik!”. (Moją ogólną zasadą jest nigdy nie używać a).
  • q dla „Zakończ ten proces”
  • d dla „Pokaż mi różnice między moim plikiem a nadpisaniem”
  • h dla ” Pokaż mi listę co oznacza Ynaqdh

w moim zgłoszeniu zaakceptowałem każde nadpisanie z Y z wyjątkiem config/routes.rbi config/locales/en.yml. Te dwa pliki były plikami, które zmieniłem, więc chciałem zachować moją wersję, więc wybrałem n.

ten proces aktualizacji może być bardziej zaangażowany, jeśli masz bardziej złożoną aplikację, szczególnie jeśli masz wiele niestandardowych konfiguracji w dowolnym z plików konfiguracyjnych środowiska, np. config/environments/production.rb, config/environments/test.rbi config/environments/development.rb. Uaktualnienie dodaje ważne ustawienia do tych plików, ale będziesz chciał również zachować własną konfigurację-tutaj pomaga posiadanie oryginalnej wersji aplikacji w oddzielnej gałęzi git. To jest możliwe do kodu w tej starej gałęzi, aby sprawdzić, czy cały kod aplikacji i konfiguracji jest nadal na miejscu po aktualizacji.

po uruchomieniu bin/bundle exec rails app:update konieczne było dla mnie dodanie klejnotu bootsnapdo Gemfile. Jest to nowy klejnot używany w Rails 5.2, ale nie jest dodawany jako część polecenia app:upgrade. Więc po prostu dodałem gem 'bootsnap' do Gemfile, a następnie uruchomiłem bin/bundle install.

po tym, moja aplikacja Bucket List uruchomiła się tak jak przed użyciem rails server.

Wymiana CarrierWave na ActiveStorage

tak więc, gdy aplikacja działa teraz na Rails 5.2, mógłbym zacząć zastępować CarrierWave na ActiveStorage.

w Activestorage nie ma potrzeby dodawania atrybutów specyficznych dla modelu, aby przechowywać nazwy plików załączników, które są niezbędne w CarrierWave. ActiveStorage działa z tymi samymi dwiema powiązanymi tabelami dla wszystkich załączników.

aby skonfigurować te dwie tabele, pobiegłem bin/bundle exec rails active_storage:install, a następnie rails db:migrate. Dwie tabele to active_storage_blobs i active_storage_attachments; pierwsza dotyczy szczegółów dołączonego pliku, a druga dotyczy tabeli polymorphic join, która łączy dołączony plik z rekordem modelu.

i tu jest ważny punkt: po utworzeniu tych dwóch tabel nie musimy tworzyć żadnych innych migracji, aby uwzględnić załączniki w naszych modelach! Dzięki temu ActiveStorage jest łatwy w obsłudze z punktu widzenia bazy danych.

następnie spojrzałem na zastąpienie implementacji załącznika :avatar activestorage zamiast CarrierWave. W mojej aplikacji każdy User ma :avatar. Ponieważ wcześniej używałem CarrierWave, miałem atrybut :avatar zamontowany do CarrierWave Uploader w modelu User, zadeklarowany w ten sposób:

class User < ApplicationRecord
# ... various codez mount_uploader :avatar, AvatarUploader # ... other codez
end

załącznik CarrierWave :avatar można zastąpić załącznikiem ActiveSupport za pomocą has_one_attached :avatar, w ten sposób:

class User < ApplicationRecord
# ... various codez # commented old uploader for reference
# mount_uploader :avatar, AvatarUploader
has_one_attached :avatar # ... other codez
end

to jest zmiana jednej linii kodu. W tym momencie, co jeszcze trzeba zrobić? Na przykład, w jaki sposób ustawiona jest lokalizacja magazynu przesyłania? Pamiętaj, że w mojej aplikacji CarrierWave Avatar uploader jest skonfigurowany z domyślnym prostym przechowywaniem plików, a lokalizacja tego jest jawnie ustawiona w pliku avatar_uploader.rb. Proste przechowywanie plików jest również domyślne w ActiveStorage. Lokalizacja jest ustawiana w pliku config/storage.yml, z domyślną wartością dla przesyłanych lokalnych.

domyślna konfiguracja ActiveStorage oznacza, że nie muszę już pisać kodu, aby moje uploady działały dla zmodyfikowanego atrybutu :avatar w mojej aplikacji. Całkowicie zmieniłem mechanizm uploadu z CarrierWave na ActiveStorage i nie muszę nic więcej robić: Nie muszę wprowadzać żadnych zmian do kontrolera, który zarządza uploadem, ponieważ :avatar jest już zadeklarowany jako silny parametr. I nie muszę zmieniać pola formularza pliku w widoku, które pozwala użytkownikom wybrać obraz do przesłania, ponieważ jest to poparte „atrybutem”:avatar.

ale jest jeszcze jedna zmiana, którą muszę wprowadzić, aby przejść z CarrierWave do ActiveStorage, a mianowicie jak korzystać z załączonego obrazu w widokach. W carierwave użyłem metody avatar_url do renderowania pełnej ścieżki obrazu. W ActiveStorage adres URL pliku nie jest renderowany z samego atrybutu attachment, ale renderowany przez przekazanie atrybutu metodom pomocniczym. Tak więc pełny adres URL załącznika może być renderowany za pomocą url_for(user.avatar)lub bezpośrednio za pomocą image_tag.

konieczne jest również wyraźne sprawdzenie, czy załącznik jest obecny, więc pełne użycie w widoku wyglądałoby mniej więcej tak:

<% if current_user.avatar.attached? %>
<%= image_tag current_user.avatar, class: 'avatar' %>
<% else %>
<%= image_tag 'default-avatar', class: 'avatar' %>
<% end %>

po zaktualizowaniu odniesień do user.avatar_url w moich poglądach za pomocą fragmentów takich jak wyżej, całkowicie przeniosłem się z CarrierWave do ActiveStorage dla wszystkich nowych uploadów.

stary kod CarrierWave musi zostać uporządkowany i pojawia się pytanie, co zrobić z istniejącymi uploadami, które zostały wykonane za pomocą CarrierWave. Ale patrz poniżej na ten temat …

bardziej złożone scenariusze

prawie wszystkie scenariusze produkcyjne będą bardziej złożone niż ten, który opisałem powyżej. Konieczne będzie rozważenie takich rzeczy, jak przesyłanie danych przechowywane na CDN lub zdalnych serwerach, takich jak AWS S3, zmiana rozmiaru obrazu dla miniatur itp. ActiveStorage pozwala nam robić wiele z tych rzeczy po wyjęciu z pudełka i wydaje się bardzo dobrze zaprojektowany dla potrzeb programistów. Jak można się spodziewać, w przewodniku Rails znajduje się dobra dokumentacja.

jeśli chodzi o migrację istniejących uploadów z CarrierWave do ActiveStorage, byłoby to z pewnością możliwe przy stosunkowo małym skrypcie rake. Postaram się to opisać w przyszłym poście.

to był prosty scenariusz, ale ogólnie byłem bardzo zadowolony z tego, jak łatwo było skorzystać z ActiveStorage i zastąpić nim CarrierWave. Podoba mi się również myśl, która przeszła do różnych części ActiveStorage, ponieważ wszystko wydaje się być w plikach i folderach, które ładnie pasują do struktury reszty Rails. Zdecydowanie uważam, że warto wejść w Rails 5.2, aby korzystać z ActiveStorage do przesyłania plików w twoich aplikacjach!

dowiedz się więcej!

chcesz dowiedzieć się więcej o Ruby i Ruby on Rails? Uczę tworzenia aplikacji internetowych w EPFL Extension School, certyfikowanej platformie edukacyjnej online, która uczy umiejętności cyfrowych w zakresie nauk o danych,tworzenia aplikacji internetowych i innych. EPFL jest jednym z wiodących uniwersytetów na świecie i jest w rankingu „numer 1 Młody Uniwersytet” przez Times Higher Education Ranking.



+