active storage+active model serializer의 N+1 문제 해결

8997 단어 Rails
개인 비망록 & 같은 고민을 하는 사람의 참고가 됐으면 좋겠다고 생각해서 쓰고 싶어요.

릴리즈

ruby 2.6.3 rails 6.0.0

before do


이 보도를 통해 처리되는 모델 관계를 사전에 잘 해라.
user와post는 일대다 관계입니다.
user.rb
class User < ApplicationRecord
  has_many :posts

  has_one_attached :avatar
end
post.rb
class Post < ApplicationRecord
  belongs_to :user

  has_many_attached :images
end

active storage + API


기사의 제목에서 약간 벗어났다.
active storge와 관련해서는 레일스뷰를 써봤는데 여러 방법이 있었지만, API에서는 그림의 URL만 답장하려다 빠져서 적어놨어요.
config/application.rb
...
require some modules
...

Bundler.require(*Rails.groups)

module YourApplicationName
  class Application < Rails::Application
    config.load_defaults 6.1

    routes.default_url_options[:host] = 'your_host' # 追加
  end
end

user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  include Rails.application.routes.url_helpers

  attributes :avatar_url, ...

  def avatar_url
    url_for(object.avatar) if object.avatar.attached?
  end
end

☝️코드 의도


그림의 URL을 얻으려면
- url_for- rails_blob_path
- rails_blob_url
쓰면 돼!그러나 Serializer 내에서는 사용할 수 없습니다.
따라서 Rails.application.routes.url_helpers 모듈이 포함됩니다.( 인용하다 )active storage + API에서 말한 바와 같이 application.rb에 host를 추가해야 한다.Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true부탁이야.

active storage+active model serializer의 N+1 문제 해결


user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  include Rails.application.routes.url_helpers

  attributes :atavar_url, ...

  has_many :posts do
    object.posts.with_attached_images
  end

  def avatar_url
    url_for(object.avatar) if object.avatar.attached?
  end
end
post_serializer.rb
class PostSerializer < ActiveModel::Serializer
  include Rails.application.routes.url_helpers

  attributes :image_urls, ...

  def image_urls
    object.images.each_with_object([]) do |image, array|
      array << url_for(image)
    end
  end
end
이렇게 느끼면 기분이 좋은 N+1 문제가 해결됩니다!with_attached_images는 모델에서 has_many_attached :images로 제작된 scope이다.has_one_attached때도 마찬가지였다.
이 역할 영역의 내용 -> scope :"with_attached_images", -> { includes(images_attachments: :blob) }인용하다

최후


이해하기 어려울지 모르지만 끝까지 읽어주셔서 감사합니다.
"더 좋은 방법이 있어요!""무슨 짓을 하는지 모르겠다", "이런 느낌의 디자인, 코딩 기법은 원래 N+1 자체가 일어나지 않는다!"등, 메모 남겨주세요

참고 자료


Github rails/rails (activestorage)
RAILS GUIDE (Active Storage Overview)

이 글에 대한 수정(2021/02/11 마감)


image_url.rb
# serializer/concerns/image_url.rb
module Concerns
  module ImageUrl
    extend ActiveSupport::Concern
    include Rails.application.routes.url_helpers

    included do
      Rails.application.routes.default_url_options[:host] = 'your_host'
    end
  end
end
이전에 상술한 것처럼 콘서트를 제작하여 대상의serializer내include에서 만든 부분
application.rb내 설정Rails.application.routes.default_url_options[:host]에서 Rails.application.routes.url_helpers을 대상의serializer내 inlucde로 수정합니다.

좋은 웹페이지 즐겨찾기