[Rails] 부분 내 부분의 render 반복을 방지하려면

빠진 점



투고 일람 페이지에 「좋아 버튼」을 설치할 때, 각 투고의 부분을 render 할 때의 반복은, collection 옵션으로 해결할 수 있었다.

그러나 각 게시물의 부분에서 render하는 부분에서는 게시물만큼 render의 반복이 발생합니다.

 ↓실제 로그

이 render 때문에 25건의 투고 표시에 1800ms 이상의 시간이 걸린다. 게다가 Ajax에 의한 비동기 처리로 좋아하는 버튼의 전환을 구현하고 있기 때문에(DRY의 관점에서도), 좋아하는 버튼을 부분화 해야 한다. (그 밖에 방법이 있으면 알고 싶습니다!) 같은 상황의 분도 많은 것은 아닌가?

해결책



render의 layout 옵션과 yield 메소드를 사용하여 해결했습니다.

ER 다이어그램





[NG패턴] render의 반복이 발생하는 render의 사용법



컨트롤러



posts_controller.rb
def index
  @posts = Post.All        # 今回はN+1問題などは考慮しません
end

보기



views/posts/index.html
%div
  = render partial: 'posts/shared/post', collection: @posts, as: :post


views/posts/shared/_post.html
%div
  = post.id
  = post.content
  .post-likes{ id: "post-#{post.id}-likes" }
      = render 'likes/like', post: post

views/likes/_like.html
- if post.already_liked?(current_user) # 「いいね」済みならtrueを返すメソッド
  = link_to post_like_path(post, post.likes), mehod: :delete, remote: true do
    %font
      .fas.fa-heart.likes-heart-already
- else
  = link_to post_likes_path(post), method: :post, remote: true do
    %font
      .far.fa-heart
%span{ id: "post-#{post.id}-likes-count" }
  = post.likes.count

로그



terminal
web_1              |   ↳ app/controllers/application_controller.rb:36
web_1              |   Rendering posts/index.html.haml within layouts/application
web_1              |   Rendered likes/_like.html.haml (7.7ms)
web_1              |   Rendered likes/_like.html.haml (0.6ms)
web_1              |   Rendered likes/_like.html.haml (0.6ms)
web_1              |   Rendered likes/_like.html.haml (0.5ms)
                                                 〜省略〜
web_1              |   Rendered likes/_like.html.haml (0.6ms)
web_1              |   Rendered likes/_like.html.haml (0.4ms)
web_1              |   Rendered likes/_like.html.haml (0.4ms)
web_1              |   Rendered collection of posts/shared/_post.html.haml [25 times] (663.9ms)
web_1              |   Rendered posts/index.html.haml within layouts/application (690.5ms)
web_1              | Completed 200 OK in 1847ms (Views: 1791.0ms | ActiveRecord: 3.4ms)

[OK 패턴] render의 반복이 발생하지 않는 render의 사용법



컨트롤러



posts_controller.rb
# コントローラは改善前と同じです。

def index
  @posts = Post.All        # 今回はN+1問題などは考慮しません
end

보기



↓ render 메소드의 layout 옵션을 사용하여 부분에 _like.html을 지정. 또한 collection에는 posts를 지정한다.

views/posts/index.html
.posts-wrap
  %div{ id: 'post-items' }
    = render partial: 'likes/like', layout: 'posts/post_layout', collection: @posts, as: :post

/ _post_layoutパーシャルは新たに作成します。

↓ yield 메소드에서 _like.html 부분을 표시한다.

views/posts/post_layout.html
%div{ id: "post-#{post.id}" }
  %div
    = post.id
    = post.content
    .post-likes{ id: "post-#{post.id}-likes" }
      = yield

/ このファイルはは新たに作成しています。

로그



terminal
web_1              |   ↳ app/controllers/application_controller.rb:36
web_1              |   Rendering posts/index.html.haml within layouts/application
web_1              |   Rendered collection of likes/_like.html.haml [25 times] (33.6ms)
web_1              |   Rendered posts/index.html.haml within layouts/application (61.2ms)
web_1              | Completed 200 OK in 343ms (Views: 295.7ms | ActiveRecord: 2.9ms)

1847ms도 필요했던 액세스 시간을 343ms까지 단축할 수 있었습니다! (정확하게는 단축은 아니지만)



어쩐지 이해한 마음이었던 render 메소드와 yield 메소드에 대해 이해를 깊게 할 수 있었습니다.
해결까지 시간이 걸려 버렸기 때문에 해결할 수 있었을 때는 정말 감동했습니다.

첫 게시물에서 이해하기 어려운 점이있을 수 있습니다.
의견, 조언 등 잘 부탁드립니다!

앞으로도 배움의 아웃풋을 해 나가고 싶습니다.

참고한 기사

좋은 웹페이지 즐겨찾기