Cała oryginalna treść jest tworzona po ukraińsku. Nie wszystkie treści zostały jeszcze przetłumaczone. Niektóre posty mogą być dostępne tylko po ukraińsku.Dowiedz się więcej
Generowanie obrazów Open Graph w Rails za pomocą szablonów SVG
Jako szablon do generowania obrazów JPG wybrałem SVG ze względu na prostotę i szybkość pracy z tym formatem. Na przykład HTML jako szablon daje więcej możliwości, ale jest bardziej skomplikowany w realizacji i utrzymaniu.
Zadanie - generacja obrazu JPG dla oznaczenia OpenGraph (to obrazek/podgląd dla niektórych mediów społecznościowych). Aplikacja Rails znajduje się na Heroku. Ilość RAM nie jest zbyt duża, więc zadanie generacji obrazu trzeba gdzieś przenieść. Konfigurowanie i płacenie za sidekiq dla projektu pet nie ma sensu. Dobrym rozwiązaniem dla mnie okazał się Heroku Scheduler. Ten standardowy (bezpłatny) dodatek będzie uruchamiał nasze zadanie rake zgodnie z harmonogramem (raz dziennie). A samo zadanie będzie znajdować posty, które jeszcze nie mają obrazu OG, i będzie je generować i dołączać (używane jest ActiveStorage, obraz zostanie przesłany na aws) do modelu.
Pierwsze, co trzeba zrobić, to stworzyć szablon SVG. Na początku bawimy się z SVG. Obraz OG ma mieć 1200px x 630px.
Oto mniej więcej jak będzie wyglądał szablon SVG:
Ten szablon nie ma żadnych zmiennych. Zmienne będą interpretowane w szablonie .erb. Umieścimy ten szablon SVG w naszej aplikacji rails i dodamy rozszerzenie .erb, na przykład lib/templates/og_image_template.svg.erb.
Używam biblioteki mini_magick. Więc już mam w Gemfile:
gem "mini_magick"
Dalej sam kod lib/cover_image_generator.rb.
require 'mini_magick'
require 'erb'
module CoverImageGenerator
class Generator
def generate_and_attach(entry, entry_title)
begin
# Dynamicznie wypełnij szablon SVG
@entry_title = entry_title.truncate(160)
@blog_name = entry.blog.slug
svg_template = File.read(File.expand_path('./templates/cover_image_template.svg.erb', __dir__))
svg_content = ERB.new(svg_template).result(binding)
# Stwórz obraz MiniMagick z zawartości SVG
cover_image = MiniMagick::Image.read(svg_content)
# Konwertuj na JPG
cover_image.format('jpg')
temp_file_path = entry.slug + '.jpg'
cover_image.write(temp_file_path)
# Dołącz obraz do wpisu
entry.cover_image.attach(io: File.open(temp_file_path), filename: "#{entry.slug}.jpg", content_type: 'image/jpeg')
# Wyczyść plik tymczasowy
File.delete(temp_file_path)
rescue => e
# Tutaj prawdopodobnie będą problemy z tekstem, który ma specyficzne znaki, które nie mogą być konwertowane na JPG.
# Na razie takie tytuły po prostu ignoruję - trzeba znaleźć rozwiązanie dla tego problemu.
# Obecnie, jeśli model nie ma dodanego obrazu OG, pokazuję domyślny obraz.
puts "Błąd na: #{@entry_title}, ID: #{entry.id}"
puts e
puts "=========================================="
end
puts "Obraz dołączony do: #{@entry_title}, ID: #{entry.id}"
puts "=========================================="
end
end
end
AWS jest już skonfigurowany i wszystko, co trzeba zrobić, to dodać cover_image do naszego modelu (na przykład Topic)
Nasz szablon SVG ma renderować nasze zmienne. Również, biorąc pod uwagę specyfikę stylów pliku SVG, musimy podzielić zbyt długie tytuły na kilka wierszy.
Ten kod należy dodać do zadania rake, które przejdzie i wygeneruje obraz OG dla wszystkich potrzebnych obiektów. Można również użyć tego kodu do generowania obrazu po utworzeniu lub aktualizacji (tytułu) obiektu.
Wynik:
Приклад створеного JPEG з SVG шаблону
Ten przykład kodu / koncepcji nie jest ostateczną wersją. Jest jeszcze nad czym pracować.