thredded 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -17
- data/app/assets/images/thredded/three-dot-menu.svg +3 -0
- data/app/assets/stylesheets/thredded/base/_tables.scss +1 -0
- data/app/assets/stylesheets/thredded/base/_variables.scss +24 -1
- data/app/assets/stylesheets/thredded/components/_currently-online.scss +1 -0
- data/app/assets/stylesheets/thredded/components/_messageboard.scss +18 -10
- data/app/assets/stylesheets/thredded/components/_post.scss +84 -13
- data/app/assets/stylesheets/thredded/components/_topics.scss +7 -1
- data/app/assets/stylesheets/thredded/layout/_main-container.scss +1 -0
- data/app/assets/stylesheets/thredded/layout/_search-navigation.scss +15 -6
- data/app/controllers/thredded/application_controller.rb +6 -3
- data/app/controllers/thredded/moderation_controller.rb +1 -1
- data/app/controllers/thredded/posts_controller.rb +19 -22
- data/app/controllers/thredded/preferences_controller.rb +1 -2
- data/app/controllers/thredded/private_posts_controller.rb +77 -0
- data/app/controllers/thredded/private_topics_controller.rb +1 -1
- data/app/controllers/thredded/read_states_controller.rb +1 -1
- data/app/controllers/thredded/topics_controller.rb +1 -1
- data/app/forms/thredded/private_topic_form.rb +3 -3
- data/app/forms/thredded/topic_form.rb +1 -1
- data/app/helpers/thredded/application_helper.rb +12 -1
- data/app/helpers/thredded/render_helper.rb +14 -0
- data/app/helpers/thredded/urls_helper.rb +8 -0
- data/app/models/concerns/thredded/post_common.rb +20 -0
- data/app/models/concerns/thredded/user_topic_read_state_common.rb +6 -0
- data/app/models/thredded/null_user_topic_read_state.rb +4 -0
- data/app/policies/thredded/post_policy.rb +4 -0
- data/app/policies/thredded/private_post_policy.rb +4 -0
- data/app/view_hooks/thredded/all_view_hooks.rb +15 -0
- data/app/view_models/thredded/base_topic_view.rb +1 -1
- data/app/view_models/thredded/post_view.rb +23 -21
- data/app/view_models/thredded/posts_page_view.rb +4 -2
- data/app/view_models/thredded/topic_posts_page_view.rb +1 -1
- data/app/view_models/thredded/topic_view.rb +1 -1
- data/app/view_models/thredded/topics_page_view.rb +1 -0
- data/app/views/thredded/moderation/_post.html.erb +2 -2
- data/app/views/thredded/moderation/_user_post.html.erb +2 -2
- data/app/views/thredded/moderation/activity.html.erb +3 -1
- data/app/views/thredded/moderation/pending.html.erb +3 -1
- data/app/views/thredded/moderation/user.html.erb +3 -1
- data/app/views/thredded/posts/_content.html.erb +1 -0
- data/app/views/thredded/posts/_post.html.erb +11 -12
- data/app/views/thredded/posts/edit.html.erb +3 -4
- data/app/views/thredded/posts_common/_actions.html.erb +21 -8
- data/app/views/thredded/posts_common/actions/_delete.html.erb +4 -0
- data/app/views/thredded/posts_common/actions/_edit.html.erb +2 -0
- data/app/views/thredded/posts_common/actions/_mark_as_unread.html.erb +2 -0
- data/app/views/thredded/private_posts/_content.html.erb +1 -0
- data/app/views/thredded/private_posts/_private_post.html.erb +5 -6
- data/app/views/thredded/private_posts/edit.html.erb +18 -0
- data/app/views/thredded/private_topics/show.html.erb +3 -1
- data/app/views/thredded/shared/_nav.html.erb +1 -1
- data/app/views/thredded/shared/nav/_standalone.html.erb +1 -1
- data/app/views/thredded/topics/_sticky_topics_divider.html.erb +1 -0
- data/app/views/thredded/topics/_topic.html.erb +4 -0
- data/app/views/thredded/topics/index.html.erb +1 -1
- data/app/views/thredded/topics/show.html.erb +1 -1
- data/app/views/thredded/users/_post.html.erb +2 -2
- data/app/views/thredded/users/_posts.html.erb +1 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/config/locales/pl.yml +1 -0
- data/config/locales/pt-BR.yml +1 -0
- data/config/routes.rb +9 -4
- data/lib/generators/thredded/install/templates/initializer.rb +7 -0
- data/lib/thredded.rb +4 -0
- data/lib/thredded/collection_to_strings_with_cache_renderer.rb +62 -0
- data/lib/thredded/version.rb +1 -1
- metadata +15 -4
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
<% post, content = post_and_content if local_assigns.key?(:post_and_content) %>
|
2
2
|
<%= content_tag :article, id: dom_id(post), class: 'thredded--post thredded--post-moderation' do %>
|
3
3
|
<%= render 'thredded/posts_common/header_with_user_and_topic',
|
4
4
|
post: post,
|
@@ -8,7 +8,7 @@
|
|
8
8
|
content_tag :em, t('thredded.null_user_name')
|
9
9
|
end
|
10
10
|
%>
|
11
|
-
<%= render
|
11
|
+
<%= content || render('thredded/posts/content', post: post) %>
|
12
12
|
<%= render 'thredded/posts_common/actions', post: post %>
|
13
13
|
<% if post.blocked? %>
|
14
14
|
<p class="thredded--alert thredded--alert-danger">
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
1
|
+
<% post, content = post_and_content if local_assigns.key?(:post_and_content) %>
|
2
2
|
<%= content_tag :article, id: dom_id(post), class: 'thredded--post thredded--post-moderation' do %>
|
3
3
|
<%= render 'thredded/posts_common/header_with_topic', post: post %>
|
4
|
-
<%= render
|
4
|
+
<%= content || render('thredded/posts/content', post: post) %>
|
5
5
|
<%= render 'thredded/posts_common/actions', post: post %>
|
6
6
|
<% if post.blocked? %>
|
7
7
|
<p class="thredded--alert thredded--alert-danger">
|
@@ -11,7 +11,9 @@
|
|
11
11
|
</div>
|
12
12
|
<% end %>
|
13
13
|
<% if @posts.present? %>
|
14
|
-
<%=
|
14
|
+
<%= render_posts @posts,
|
15
|
+
partial: 'thredded/moderation/post',
|
16
|
+
content_partial: 'thredded/posts/content' %>
|
15
17
|
<%= paginate @posts %>
|
16
18
|
<% end %>
|
17
19
|
<% end %>
|
@@ -10,7 +10,9 @@
|
|
10
10
|
</div>
|
11
11
|
<% end %>
|
12
12
|
<% if @posts.present? %>
|
13
|
-
<%=
|
13
|
+
<%= render_posts @posts,
|
14
|
+
partial: 'thredded/moderation/post',
|
15
|
+
content_partial: 'thredded/posts/content' %>
|
14
16
|
<%= paginate @posts %>
|
15
17
|
<% else %>
|
16
18
|
<div class="thredded--empty">
|
@@ -42,7 +42,9 @@
|
|
42
42
|
<% end %>
|
43
43
|
<% if @posts.present? %>
|
44
44
|
<h2><%= t 'thredded.users.recent_activity' %></h2>
|
45
|
-
<%=
|
45
|
+
<%= render_posts @posts,
|
46
|
+
partial: 'thredded/moderation/user_post',
|
47
|
+
content_partial: 'thredded/posts/content' %>
|
46
48
|
<%= paginate @posts %>
|
47
49
|
<% end %>
|
48
50
|
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'thredded/posts_common/content', post: post %>
|
@@ -1,14 +1,13 @@
|
|
1
|
-
<%
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<% end %>
|
1
|
+
<% post, content = post_and_content if local_assigns.key?(:post_and_content) %>
|
2
|
+
<%= content_tag :article, id: dom_id(post), class: "thredded--post thredded--#{post.read_state}--post" do %>
|
3
|
+
<%= render 'thredded/posts_common/actions', post: post %>
|
4
|
+
<%= render 'thredded/posts_common/header', post: post %>
|
5
|
+
<%= content || render('thredded/posts/content', post: post) %>
|
6
|
+
<% if post.pending_moderation? && !Thredded.content_visible_while_pending_moderation %>
|
7
|
+
<p class="thredded--alert thredded--alert-warning"><%= t 'thredded.posts.pending_moderation_notice' %></p>
|
8
|
+
<% elsif post.blocked? && post.can_moderate? %>
|
9
|
+
<p class="thredded--alert thredded--alert-danger">
|
10
|
+
<%= render 'thredded/shared/content_moderation_blocked_state', moderation_record: post.last_moderation_record %>
|
11
|
+
</p>
|
13
12
|
<% end %>
|
14
13
|
<% end %>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<% content_for :thredded_page_title, '
|
1
|
+
<% content_for :thredded_page_title, t('thredded.nav.edit_post') %>
|
2
2
|
<% content_for :thredded_page_id, 'thredded--edit-post' %>
|
3
3
|
<% content_for :thredded_breadcrumbs do %>
|
4
4
|
<ul class="thredded--navigation-breadcrumbs">
|
@@ -9,11 +9,10 @@
|
|
9
9
|
<%= thredded_page do %>
|
10
10
|
<section class="thredded--main-section">
|
11
11
|
<%= render 'thredded/posts/form',
|
12
|
-
messageboard:
|
12
|
+
messageboard: messageboard,
|
13
13
|
topic: topic,
|
14
14
|
post: @post,
|
15
|
-
preview_url: (
|
16
|
-
: messageboard_topic_post_preview_path(messageboard, @post.postable, @post)),
|
15
|
+
preview_url: messageboard_topic_post_preview_path(messageboard, @post.postable, @post),
|
17
16
|
button_text: t('thredded.posts.form.update_btn'),
|
18
17
|
button_submitting_text: t('thredded.posts.form.update_btn_submitting')%>
|
19
18
|
</section>
|
@@ -1,11 +1,24 @@
|
|
1
|
-
<%
|
2
|
-
<%=
|
1
|
+
<% actions = capture do %>
|
2
|
+
<%= view_hooks.post_common.actions.render self, post: post do %>
|
3
|
+
<% if post.can_update? %>
|
4
|
+
<%= render 'thredded/posts_common/actions/edit', post: post %>
|
5
|
+
<% end %>
|
6
|
+
<% if post.can_destroy? %>
|
7
|
+
<%= render 'thredded/posts_common/actions/delete', post: post %>
|
8
|
+
<% end %>
|
9
|
+
<% if post.read_state %>
|
10
|
+
<%= view_hooks.post_common.mark_as_unread.render self, post: post do %>
|
11
|
+
<%= render 'thredded/posts_common/actions/mark_as_unread', post: post %>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
3
15
|
<% end %>
|
4
16
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
17
|
+
<%- if actions.present? %>
|
18
|
+
<div class='thredded--post--dropdown'>
|
19
|
+
<%= inline_svg 'thredded/three-dot-menu.svg', class: 'thredded--post--dropdown--toggle' %>
|
20
|
+
<div class='thredded--post--dropdown--actions'>
|
21
|
+
<%= actions %>
|
22
|
+
</div>
|
23
|
+
</div>
|
11
24
|
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'thredded/posts_common/content', post: post %>
|
@@ -1,7 +1,6 @@
|
|
1
|
-
<%
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
<% end %>
|
1
|
+
<% private_post, content = post_and_content if local_assigns.key?(:post_and_content) %>
|
2
|
+
<%= content_tag :article, id: dom_id(private_post), class: 'thredded--post' do %>
|
3
|
+
<%= render 'thredded/posts_common/actions', post: private_post %>
|
4
|
+
<%= render 'thredded/posts_common/header', post: private_post %>
|
5
|
+
<%= content || render('thredded/private_posts/content', post: post) %>
|
7
6
|
<% end %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% content_for :thredded_page_title, t('thredded.nav.edit_post') %>
|
2
|
+
<% content_for :thredded_page_id, 'thredded--edit-post' %>
|
3
|
+
<% content_for :thredded_breadcrumbs do %>
|
4
|
+
<ul class="thredded--navigation-breadcrumbs">
|
5
|
+
<li><%= link_to t('thredded.nav.edit_post'), edit_post_path(@post) %></li>
|
6
|
+
</ul>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<%= thredded_page do %>
|
10
|
+
<section class="thredded--main-section">
|
11
|
+
<%= render 'thredded/posts/form',
|
12
|
+
topic: topic,
|
13
|
+
post: @post,
|
14
|
+
preview_url: private_topic_private_post_preview_path(@post.postable, @post),
|
15
|
+
button_text: t('thredded.posts.form.update_btn'),
|
16
|
+
button_submitting_text: t('thredded.posts.form.update_btn_submitting')%>
|
17
|
+
</section>
|
18
|
+
<% end %>
|
@@ -11,7 +11,9 @@
|
|
11
11
|
<%= view_hooks.posts_common.pagination_top.render(self, posts: @posts) do %>
|
12
12
|
<footer class="thredded--pagination-top"><%= paginate @posts %></footer>
|
13
13
|
<% end %>
|
14
|
-
<%=
|
14
|
+
<%= render_posts @posts,
|
15
|
+
partial: 'thredded/private_posts/private_post',
|
16
|
+
content_partial: 'thredded/private_posts/content' %>
|
15
17
|
<%= view_hooks.posts_common.pagination_bottom.render(self, posts: @posts) do %>
|
16
18
|
<footer class="thredded--pagination-bottom"><%= paginate @posts %></footer>
|
17
19
|
<% end %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<nav class="thredded--navigation">
|
2
2
|
<ul class="thredded--user-navigation<%= ' thredded--user-navigation-standalone' if Thredded.standalone_layout? %>">
|
3
|
-
<% if
|
3
|
+
<% if thredded_signed_in? && Thredded.standalone_layout? %>
|
4
4
|
<li class="thredded--user-navigation--profile thredded--user-navigation--item">
|
5
5
|
<%= link_to thredded_current_user.thredded_display_name, user_path(thredded_current_user) %>
|
6
6
|
</li>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<li class="thredded--user-navigation--standalone thredded--user-navigation--item">
|
2
2
|
<% resource_name = Thredded.user_class.name.underscore %>
|
3
|
-
<% if
|
3
|
+
<% if thredded_signed_in? %>
|
4
4
|
<%= link_to main_app.send(:"destroy_#{resource_name}_session_path"), method: :delete do %>
|
5
5
|
<span>Sign Out</span>
|
6
6
|
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<hr class="thredded--topics--sticky-topics-divider">
|
@@ -15,7 +15,7 @@
|
|
15
15
|
css_class: 'thredded--is-compact',
|
16
16
|
preview_url: preview_new_messageboard_topic_path(messageboard),
|
17
17
|
placeholder: t('thredded.topics.form.title_placeholder_start') if @new_topic %>
|
18
|
-
<%= render @topics %>
|
18
|
+
<%= render partial: 'thredded/topics/topic', collection: @topics, locals: {topics: @topics} %>
|
19
19
|
<% end %>
|
20
20
|
|
21
21
|
<footer class="thredded--pagination-bottom">
|
@@ -12,7 +12,7 @@
|
|
12
12
|
<%= view_hooks.posts_common.pagination_top.render(self, posts: @posts) do %>
|
13
13
|
<footer class="thredded--pagination-top"><%= paginate @posts %></footer>
|
14
14
|
<% end %>
|
15
|
-
<%=
|
15
|
+
<%= render_posts @posts, partial: 'thredded/posts/post', content_partial: 'thredded/posts/content' %>
|
16
16
|
<%= view_hooks.posts_common.pagination_bottom.render(self, posts: @posts) do %>
|
17
17
|
<footer class="thredded--pagination-bottom"><%= paginate @posts %></footer>
|
18
18
|
<% end %>
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
<% post, content = post_and_content if local_assigns.key?(:post_and_content) %>
|
2
2
|
<%= content_tag :article, id: dom_id(post), class: 'thredded--post' do %>
|
3
3
|
<%= render 'thredded/posts_common/header_with_topic', post: post %>
|
4
|
-
<%= render
|
4
|
+
<%= content || render('thredded/posts/content', post: post) %>
|
5
5
|
<%= render 'thredded/posts_common/actions', post: post %>
|
6
6
|
<% end %>
|
@@ -4,4 +4,4 @@
|
|
4
4
|
TODO: Use a Cell instead. https://github.com/apotonick/cells
|
5
5
|
%>
|
6
6
|
<%# @param posts [Thredded::PostsPageView] %>
|
7
|
-
<%=
|
7
|
+
<%= render_posts posts, partial: 'thredded/users/post', content_partial: 'thredded/posts/content' %>
|
data/config/locales/en.yml
CHANGED
data/config/locales/es.yml
CHANGED
data/config/locales/pl.yml
CHANGED
@@ -156,6 +156,7 @@ pl:
|
|
156
156
|
update_btn: Zaktualizuj temat
|
157
157
|
locked:
|
158
158
|
label: Zablokowany
|
159
|
+
mark_as_unread: Oznacz jako nieprzeczytane stąd
|
159
160
|
not_following: Nie obserwujesz tego tematu.
|
160
161
|
search:
|
161
162
|
no_results_message: 'Nie odnaleziono żadnych wyników dla frazy: %{query}'
|
data/config/locales/pt-BR.yml
CHANGED
@@ -160,6 +160,7 @@ pt-BR:
|
|
160
160
|
update_btn: Atualizar Tópico
|
161
161
|
locked:
|
162
162
|
label: Trancado
|
163
|
+
mark_as_unread: Marca não lida a partir daqui
|
163
164
|
not_following: Você não está seguindo este tema.
|
164
165
|
search:
|
165
166
|
no_results_message: Nenhum resultado encontrado para sua busca - %{query}
|
data/config/routes.rb
CHANGED
@@ -2,8 +2,7 @@
|
|
2
2
|
Thredded::Engine.routes.draw do # rubocop:disable Metrics/BlockLength
|
3
3
|
resource :theme_preview, only: [:show], path: 'theme-preview' if %w(development test).include? Rails.env
|
4
4
|
|
5
|
-
|
6
|
-
page_constraint = { page: positive_int }
|
5
|
+
page_constraint = { page: /[1-9]\d*/ }
|
7
6
|
|
8
7
|
scope path: 'private-topics' do
|
9
8
|
resource :read_state, only: [:update], as: :mark_all_private_topics_read
|
@@ -14,14 +13,17 @@ Thredded::Engine.routes.draw do # rubocop:disable Metrics/BlockLength
|
|
14
13
|
member do
|
15
14
|
get '(page-:page)', action: :show, as: '', constraints: page_constraint
|
16
15
|
end
|
17
|
-
resources :private_posts, path: '', except: [:index, :show]
|
16
|
+
resources :private_posts, path: '', except: [:index, :show] do
|
18
17
|
post :preview, on: :new, controller: 'private_post_previews'
|
19
18
|
resource :preview, only: [:update], controller: 'private_post_previews'
|
19
|
+
member do
|
20
|
+
post 'mark_as_unread'
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
24
|
-
scope only: [:show], constraints: { id:
|
26
|
+
scope only: [:show], constraints: { id: Thredded.routes_id_constraint } do
|
25
27
|
resources :private_post_permalinks, path: 'private-posts'
|
26
28
|
resources :post_permalinks, path: 'posts'
|
27
29
|
end
|
@@ -71,6 +73,9 @@ Thredded::Engine.routes.draw do # rubocop:disable Metrics/BlockLength
|
|
71
73
|
resources :posts, except: [:index, :show], path: '' do
|
72
74
|
post :preview, on: :new, controller: 'post_previews'
|
73
75
|
resource :preview, only: [:update], controller: 'post_previews'
|
76
|
+
member do
|
77
|
+
post 'mark_as_unread'
|
78
|
+
end
|
74
79
|
end
|
75
80
|
end
|
76
81
|
end
|
@@ -29,6 +29,13 @@ Thredded.current_user_method = :"current_#{Thredded.user_class.name.underscore}"
|
|
29
29
|
# User avatar URL. rb-gravatar gem is used by default:
|
30
30
|
Thredded.avatar_url = ->(user) { Gravatar.src(user.email, 128, 'mm') }
|
31
31
|
|
32
|
+
# ==> Database Configuration
|
33
|
+
# By default, thredded uses integers for record ID route constraints.
|
34
|
+
# For integer based IDs (default):
|
35
|
+
# Thredded.routes_id_constraint = /[1-9]\d*/
|
36
|
+
# For UUID based IDs (example):
|
37
|
+
# Thredded.routes_id_constraint = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
|
38
|
+
|
32
39
|
# ==> Permissions Configuration
|
33
40
|
# By default, thredded uses a simple permission model, where all the users can post to all message boards,
|
34
41
|
# and admins and moderators are determined by a flag on the users table.
|
data/lib/thredded.rb
CHANGED
@@ -39,6 +39,8 @@ require 'thredded/view_hooks/renderer'
|
|
39
39
|
# Require Thredded::ContentFormatter explicitly so that it doesn't need to be required if used in the initializer.
|
40
40
|
require 'thredded/content_formatter'
|
41
41
|
|
42
|
+
require 'thredded/collection_to_strings_with_cache_renderer'
|
43
|
+
|
42
44
|
module Thredded
|
43
45
|
mattr_accessor \
|
44
46
|
:autocomplete_min_length,
|
@@ -48,6 +50,7 @@ module Thredded
|
|
48
50
|
:email_outgoing_prefix,
|
49
51
|
:layout,
|
50
52
|
:messageboards_order,
|
53
|
+
:routes_id_constraint,
|
51
54
|
:user_class,
|
52
55
|
:user_display_name_method,
|
53
56
|
:user_name_column,
|
@@ -92,6 +95,7 @@ module Thredded
|
|
92
95
|
self.show_topic_followers = false
|
93
96
|
self.messageboards_order = :position
|
94
97
|
self.autocomplete_min_length = 2
|
98
|
+
self.routes_id_constraint = /[1-9]\d*/
|
95
99
|
|
96
100
|
# @return [Thredded::AllViewHooks] View hooks configuration.
|
97
101
|
def self.view_hooks
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'action_view/renderer/abstract_renderer'
|
3
|
+
module Thredded
|
4
|
+
class CollectionToStringsWithCacheRenderer < ActionView::AbstractRenderer
|
5
|
+
# @param view_context
|
6
|
+
# @param collection [Array<T>]
|
7
|
+
# @param partial [String]
|
8
|
+
# @param expires_in [ActiveSupport::Duration]
|
9
|
+
# @return Array<[T, String]>
|
10
|
+
def render_collection_to_strings_with_cache( # rubocop:disable Metrics/ParameterLists
|
11
|
+
view_context, collection:, partial:, expires_in:, locals: {}, **opts
|
12
|
+
)
|
13
|
+
template = @lookup_context.find_template(partial, [], true, locals, {})
|
14
|
+
collection = collection.to_a
|
15
|
+
instrument(:collection, count: collection.size) do |instrumentation_payload|
|
16
|
+
return [] if collection.blank?
|
17
|
+
keyed_collection = collection.each_with_object({}) do |item, hash|
|
18
|
+
key = ActiveSupport::Cache.expand_cache_key(
|
19
|
+
view_context.cache_fragment_name(item, virtual_path: template.virtual_path), :views
|
20
|
+
)
|
21
|
+
# #read_multi & #write may require key mutability, Dalli 2.6.0.
|
22
|
+
hash[key.frozen? ? key.dup : key] = item
|
23
|
+
end
|
24
|
+
cache = collection_cache
|
25
|
+
cached_partials = cache.read_multi(*keyed_collection.keys)
|
26
|
+
instrumentation_payload[:cache_hits] = cached_partials.size if instrumentation_payload
|
27
|
+
|
28
|
+
collection_to_render = keyed_collection.reject { |key, _| cached_partials.key?(key) }.values
|
29
|
+
rendered_partials = render_partials(
|
30
|
+
view_context, collection: collection_to_render, partial: partial, locals: locals, **opts
|
31
|
+
).each
|
32
|
+
|
33
|
+
keyed_collection.map do |cache_key, item|
|
34
|
+
[item, cached_partials[cache_key] || rendered_partials.next.tap do |rendered|
|
35
|
+
cache.write(cache_key, rendered, expires_in: expires_in)
|
36
|
+
end]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def collection_cache
|
44
|
+
if ActionView::PartialRenderer.respond_to?(:collection_cache)
|
45
|
+
# Rails 5.0+
|
46
|
+
ActionView::PartialRenderer.collection_cache
|
47
|
+
else
|
48
|
+
# Rails 4.2.x
|
49
|
+
Rails.application.config.action_controller.cache_store
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Array<String>]
|
54
|
+
def render_partials(view_context, collection:, **opts)
|
55
|
+
return [] if collection.empty?
|
56
|
+
partial_renderer = ActionView::PartialRenderer.new(@lookup_context)
|
57
|
+
collection.map do |item|
|
58
|
+
partial_renderer.render(view_context, opts.merge(object: item), nil)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|