thredded 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|