Microlink를 사용하여 Rails에서 링크 미리 보기 생성
1단계: 애플리케이션 설정
rails new rails-microlink-example -d=postgresql --webpacker=stimulus
rails db:create
rails db:migrate
2단계: 링크 스캐폴드 생성
rails g scaffold link url:string
class CreateLinks < ActiveRecord::Migration[6.1]
def change
create_table :links do |t|
t.string :url, null: false
t.timestamps
end
end
end
rails db:migrate
class Link < ApplicationRecord
validates :url, presence: true
end
3단계. 링크 테이블에 meta_data 열 추가
rails add_meta_data_to_link meta_data:jsonb
rails db:migrate
meta_data
열에 저장된 데이터를 직렬화합니다. 이러한 접근자를 원하는 대로 호출할 수 있지만 Microlink response에서 반환된 동일한 이름을 사용합니다.class Link < ApplicationRecord
store :meta_data, accessors: [ :description, :image, :title ], coder: JSON
validates :url, presence: true
end
We could create a separate column for each
accessor
, but usingActiveRecord::Store
allows for greater flexibly and keeps the database simple.
link_params
열의 값을 포함하도록 meta_data
를 업데이트합니다.class LinksController < ApplicationController
...
private
...
def link_params
params.require(:link).permit(:url, :description, :image, :title)
end
end
4단계: Microlink 설치 및 구성
yarn add @microlink/mql
touch app/javascript/controllers/microlink_controller.js
import { Controller } from "stimulus"
import mql from "@microlink/mql"
export default class extends Controller {
}
If you were you run
rails s
and view the console, you would see the following error:
babel.config.js
를 추가하여 sourceType: "unambiguous"
를 업데이트합니다.module.exports = function(api) {
...
return {
sourceType: "unambiguous",
presets: [
...
].filter(Boolean),
...
}
}
I found this solution be searching for the error and came across these resources:
5단계: 숨겨진 필드에 API 응답 저장
app/views/links/_form.html.erb
에서 마크업을 업데이트합니다.<%= form_with(model: link, data: { controller: "microlink" }) do |form| %>
...
<div class="field">
<%= form.label :url %>
<%= form.url_field :url, data: { microlink_target: "input", action: "change->microlink#handleChange" } %>
</div>
<%= form.hidden_field :description, data: { microlink_target: "descriptionInput" } %>
<%= form.hidden_field :image, data: { microlink_target: "imageInput" } %>
<%= form.hidden_field :title, data: { microlink_target: "titleInput" } %>
...
<% end %>
handleChange
에서 app/javascript/controllers/microlink_controller.js
메서드를 빌드합니다.import { Controller } from "stimulus"
import mql from "@microlink/mql"
export default class extends Controller {
static targets = [ "input", "descriptionInput", "imageInput", "titleInput" ]
async handleChange() {
const { status, data } = await mql(this.inputTarget.value)
if(status == "success") {
this.setFormData(data);
}
}
setFormData(data) {
this.descriptionInputTarget.value = data?.description ? data?.description : null;
this.imageInputTarget.value = data?.image?.url ? data?.image?.url : null;
this.titleInputTarget.value = data?.title ? data?.title : null;
}
}
Now when a user enters a URL, the hidden fields will be set with the response from the Microlink API.
6단계: 링크 미리보기 렌더링
app/views/links/_preview.html.erb
부분을 만듭니다.<div data-microlink-target="output" style="<%= @link.persisted? ? nil : 'display: none;' %>">
<img src="<%= @link.persisted? ? @link.image : nil %>"/>
<div>
<h5><%= @link.persisted? ? @link.title : nil %></h5>
<p><%= @link.persisted? ? @link.description : nil %></p>
</div>
</div>
app/views/links/_form.html.erb
에 추가합니다.<%= form_with(model: link, data: { controller: "microlink" }) do |form| %>
...
<%= render "preview" %>
<% end %>
app/views/links/show.html.erb
에 추가합니다.<p id="notice"><%= notice %></p>
<p>
<strong>Url:</strong>
<%= @link.url %>
</p>
<%= link_to @link.url, target: "_blank" do %>
<%= render "preview" %>
<% end %>
<%= link_to 'Edit', edit_link_path(@link) %> |
<%= link_to 'Back', links_path %>
renderPreview
에서 app/javascript/controllers/microlink_controller.js
메서드를 빌드합니다.import { Controller } from "stimulus"
import mql from "@microlink/mql"
export default class extends Controller {
static targets = [ "input", "descriptionInput", "imageInput", "titleInput", "output" ]
connect() {
this.previewDescription = this.outputTarget.querySelector("p");
this.previewImage = this.outputTarget.querySelector("img");
this.previewTitle = this.outputTarget.querySelector("h5");
}
async handleChange() {
const { status, data } = await mql(this.inputTarget.value)
if(status == "success") {
this.setFormData(data);
this.renderPreview(data);
}
}
renderPreview(data) {
this.previewDescription.innerHTML = data?.description ? data.description : null;
data?.image?.url ? this.previewImage.setAttribute("src", data.image.url) : null;
this.previewTitle.innerHTML = data?.title ? data.title : null;
this.outputTarget.style.display = "block";
}
setFormData(data) {
this.descriptionInputTarget.value = data?.description ? data.description : null;
this.imageInputTarget.value = data?.image?.url ? data.image.url : null;
this.titleInputTarget.value = data?.title ? data.title : null;
}
}
At this point you should be able to render a link preview.
.
7단계: 미리보기 이미지를 링크에 첨부
지금은 실제로 이미지를
Link
에 첨부하는 것이 아니라 절대 URL을 이미지에 저장하고 있습니다. 이는 우리가 제어할 수 없기 때문에 시간이 지남에 따라 해당 이미지가 깨질 수 있음을 의미합니다. 한 가지 해결책은 이미지를 다운로드하고 Active Storage을 사용하여 Link
에 첨부하는 것입니다.rails active_storage:install
및 rails db:migrate
를 실행하여 Active Storage를 설치합니다. has_one_attached :thumbnail
를 추가합니다.class Link < ApplicationRecord
store :meta_data, accessors: [ :description, :image, :title ], coder: JSON
validates :url, presence: true
has_one_attached :thumbnail
end
bundle add down
를 실행하여 down gem을(를) 설치합니다. 이렇게 하면 기본 Ruby를 사용하여 수행하는 것보다 Microlink API에서 반환된 원격 이미지를 더 쉽게 다운로드할 수 있습니다. rails g job microlink_image_attacher
를 실행하여 Active Job을 생성합니다. 이 작업을 사용하여 Microlink API에서 반환된 이미지를 다운로드하고 첨부합니다.require "down"
class MicrolinkImageAttacherJob < ApplicationJob
queue_as :default
discard_on Down::InvalidUrl
def perform(link)
if link.image.present?
tempfile = Down.download(link.image)
link.thumbnail.attach(io: tempfile, filename: tempfile.original_filename)
end
end
end
We add
discard_on Down::InvalidUrl
to discard any job that returns aDown::InvalidUrl
exception. This can happen is the Microlink API returns a base64 image.
class LinksController < ApplicationController
...
def create
@link = Link.new(link_params)
respond_to do |format|
if @link.save
MicrolinkImageAttacherJob.perform_now(@link)
...
else
...
end
end
end
end
You could call
perform_later
instead ofperform_now
.
app/views/links/_preview.html.erb
에서 첨부된 축소판을 렌더링합니다.<div data-microlink-target="output" style="<%= @link.persisted? ? nil : 'display: none;' %>">
<img src="<%= @link.thumbnail.attached? ? url_for(@link.thumbnail) : nil %>"/>
<div>
<h5><%= @link.persisted? ? @link.title : nil %></h5>
<p><%= @link.persisted? ? @link.description : nil %></p>
</div>
</div>
이제 이미지를 반환하는 링크를 저장하면 활성 저장소에 저장됩니다.
8단계: 오류 처리 및 UX 개선
이제 행복한 길을 완성했으므로 모든 오류를 설명하기 위해 UX를 개선해야 합니다. 특히 누군가 잘못된 URL을 입력하거나 Microlink API가 오류를 반환하는 경우입니다.
app/views/links/_form.html.erb
에 메시지를 렌더링하기 위한 마크업을 추가합니다.<%= form_with(model: link, data: { controller: "microlink" }) do |form| %>
...
<div class="field">
<%= form.label :url %>
<%= form.url_field :url, data: { microlink_target: "input", action: "change->microlink#handleChange" } %>
<span data-microlink-target="message"></span>
</div>
...
<%= render "preview" %>
<% end %>
app/javascript/controllers/microlink_controller.js
합니다.import { Controller } from "stimulus"
import mql from "@microlink/mql"
export default class extends Controller {
static targets = [ "input", "descriptionInput", "imageInput", "titleInput", "output", "message" ]
connect() {
this.previewDescription = this.outputTarget.querySelector("p");
this.previewImage = this.outputTarget.querySelector("img");
this.previewTitle = this.outputTarget.querySelector("h5");
}
async handleChange() {
this.messageTarget.innerText = null;
this.clearFormData();
this.clearPreview();
if (this.inputTarget.value != "") {
try {
const { status, data } = await mql(this.inputTarget.value)
this.messageTarget.innerText = "Fetching link preview...";
if(status == "success") {
this.setFormData(data);
this.renderPreview(data);
this.messageTarget.innerText = null;
} else {
this.messageTarget.innerText = "There was an error fetching the link preview.";
}
} catch(e) {
this.messageTarget.innerText = e;
}
}
}
clearFormData() {
this.descriptionInputTarget.value = null;
this.imageInputTarget.value = null;
this.titleInputTarget.value = null;
}
clearPreview() {
this.previewDescription.innerHTML = null;
this.previewImage.setAttribute("src", "");
this.previewTitle.innerHTML = null;
this.outputTarget.style.display = "none";
}
renderPreview(data) {
this.previewDescription.innerHTML = data?.description ? data.description : null;
data?.image?.url ? this.previewImage.setAttribute("src", data.image.url) : null;
this.previewTitle.innerHTML = data?.title ? data.title : null;
this.outputTarget.style.display = "block";
}
setFormData(data) {
this.descriptionInputTarget.value = data?.description ? data.description : null;
this.imageInputTarget.value = data?.image?.url ? data.image.url : null;
this.titleInputTarget.value = data?.title ? data.title : null;
}
}
이 게시물이 마음에 드셨나요? 더 많은 팁을 얻으려면.
Reference
이 문제에 관하여(Microlink를 사용하여 Rails에서 링크 미리 보기 생성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/stevepolitodesign/generate-link-previews-in-rails-with-microlink-2aio텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)