Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
258be6f
-1 query
drusepth Aug 3, 2021
f3e61a2
-~3 queries
drusepth Aug 3, 2021
8223f99
query smaller table
drusepth Aug 3, 2021
1b50e1b
break cache methods out
drusepth Aug 3, 2021
753452f
contrib helper cache
drusepth Aug 3, 2021
062fef2
don't requery if we repeat a cache call
drusepth Aug 3, 2021
8bad60a
rewrite cache_linkable_content_for_each_content_type with far fewer q…
drusepth Aug 3, 2021
2eb50f5
only query for contributable content if you're a contributor to any u…
drusepth Aug 3, 2021
64715d3
collapse the loops
drusepth Aug 3, 2021
3362596
tweak cache guards
drusepth Aug 3, 2021
34b5c75
reuse linkables cache instead of making new queries
drusepth Aug 3, 2021
832bb92
remove user#linkable_universes
drusepth Aug 3, 2021
7aed61d
freeze AC strings
drusepth Aug 3, 2021
b2ef0f5
helper for recently-created pages cache
drusepth Aug 3, 2021
1b99bdf
remove unnecessary queries
drusepth Aug 3, 2021
fb8e298
add header to recent edits stream
drusepth Aug 3, 2021
f23522e
reuse user method for cache
drusepth Aug 3, 2021
3db83d9
reuse cached universes to fetch ids
drusepth Aug 3, 2021
dd969ba
scratch that, lol
drusepth Aug 3, 2021
7aafbdd
freeze strings in ContentController
drusepth Aug 3, 2021
54b1c43
skip ui cache on content api calls
drusepth Aug 3, 2021
f977c58
simplify valid_content_types usage
drusepth Aug 3, 2021
4a48dc0
standardize @current_user_content vs @linkables
drusepth Aug 3, 2021
512bff2
move the old doc user includes
drusepth Aug 3, 2021
a6d169f
this removes ~100 field queries for default character template, oof
drusepth Aug 3, 2021
8929447
codesmell todo
drusepth Aug 3, 2021
08b86f1
kill N+1s for loading AttributeCategories from template also
drusepth Aug 3, 2021
d8b7e3b
remove yet another set of n+1
drusepth Aug 3, 2021
010f57c
skip ui cache on document update
drusepth Aug 3, 2021
8bad87b
doc update readability
drusepth Aug 3, 2021
56cb9a6
remove animate-rails
drusepth Aug 4, 2021
7ceb687
secure universe session var
drusepth Aug 8, 2021
3f18f8c
wip before going down the ContentPage rabbit hole
drusepth Aug 8, 2021
4e782bf
include contributed content in contributable content
drusepth Aug 9, 2021
0d5e6db
rewrite linkable content caching again, to exclude current_user_contn…
drusepth Aug 9, 2021
b12900a
clean up previous commit
drusepth Aug 9, 2021
5c97273
WIP migrating to wide ContentPage usage
drusepth Aug 9, 2021
d614ee1
Merge branch 'master' into august-perf
drusepth Aug 9, 2021
2fb7218
fix default image url
drusepth Aug 9, 2021
e4e5485
re-enable universe filtering on timelines#index
drusepth Aug 9, 2021
7926712
use contentpages in serendipitous
drusepth Aug 9, 2021
ac4c3db
linkables cache safety
drusepth Aug 11, 2021
ed71129
get serendipitous questions working on content#index for ContentPage …
drusepth Aug 12, 2021
09f248d
save a bunch of queries by using cached ContentPages on dashboard
drusepth Aug 12, 2021
56f2b41
use ContentPage piping on prompts page
drusepth Aug 12, 2021
22d199a
clean up code rework
drusepth Aug 12, 2021
406105e
move references into a job (needs tested)
drusepth Aug 13, 2021
45aa1b6
Merge branch 'master' into august-perf
drusepth Oct 1, 2021
1720c84
nix a query
drusepth Oct 1, 2021
6a208e3
remove set_universe_scope dependence on current_user_content cache
drusepth Oct 1, 2021
979ee7e
document universe filter banner redesign
drusepth Oct 1, 2021
5f8153c
touch timelines when timeline events are created to make sure updated…
drusepth Oct 1, 2021
5866cf5
Merge branch 'master' into august-perf
drusepth Oct 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
WIP migrating to wide ContentPage usage
  • Loading branch information
drusepth committed Aug 9, 2021
commit 5c972738db1686748f65671a98ff7b2544db73ea
48 changes: 48 additions & 0 deletions app/authorizers/content_page_authorizer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class ContentPageAuthorizer < CoreContentAuthorizer
def self.creatable_by?(user)
return false unless user.present?
return false if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(user.email)

if resource.page_type == 'Universe'
return true if PermissionService.user_has_fewer_owned_universes_than_plan_limit?(user: user)

else
is_premium_page = Rails.application.config.content_types[:premium].include?(resource.page_type)
return true if !is_premium_page
return true if is_premium_page && PermissionService.user_is_on_premium_plan?(user: user)
end

return false
end

def readable_by?(user)
return true if PermissionService.content_is_public?(content: resource)
return true if PermissionService.user_owns_content?(user: user, content: resource)

if resource.page_type == 'Universe'
return true if PermissionService.user_can_contribute_to_universe?(user: user, universe: resource)
else
return true if PermissionService.user_can_contribute_to_containing_universe?(user: user, content: resource)
end

return false
end

def updatable_by?(user)
return true if PermissionService.user_owns_content?(user: user, content: resource)

if resource.page_type == 'Universe'
return true if PermissionService.user_can_contribute_to_universe?(user: user, universe: resource)
else
return true if PermissionService.user_can_contribute_to_containing_universe?(user: user, content: resource)
end

return false
end

def deletable_by?(user)
[
PermissionService.user_owns_content?(user: user, content: resource)
].any?
end
end
1 change: 1 addition & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def cache_linkable_content_for_each_content_type
end

filtered_fields = ContentPage.polymorphic_content_fields.map(&:to_s)
filtered_fields.push 'universe_id' unless page_type == Universe.name
pages_to_add.each do |page_data|
filtered_page_data = page_data.attributes.slice(*filtered_fields)
@linkables_raw[page_type].push ContentPage.new(filtered_page_data)
Expand Down
44 changes: 28 additions & 16 deletions app/controllers/content_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,45 @@ class ContentController < ApplicationController
before_action :set_sidenav_expansion, except: [:api_sort]

def index
cache_linkable_content_for_each_content_type

@content_type_class = content_type_from_controller(self.class)
pluralized_content_name = @content_type_class.name.downcase.pluralize

@page_title = "My #{pluralized_content_name}"

# Create the default fields for this user if they don't have any already
# TODO: uh, this probably doesn't belong here!
@content_type_class.attribute_categories(current_user)

if @universe_scope.present? && @content_type_class != Universe
@content = @universe_scope.send(pluralized_content_name)
.includes(:page_tags, :image_uploads)
.unarchived
# Linkables cache is already scoped per-universe, includes contributor pages
@content = @linkables_raw.fetch(@content_type_class.name, [])

@show_scope_notice = true
else
@content = (
current_user.send(pluralized_content_name).unarchived.includes(:page_tags, :image_uploads) +
current_user.send("contributable_#{pluralized_content_name}").unarchived.includes(:page_tags, :image_uploads)
)
@show_scope_notice = @universe_scope.present? && content_type_class != Universe

if @content_type_class != Universe
my_universe_ids = current_user.universes.pluck(:id)
@content.concat(@content_type_class.where(universe_id: my_universe_ids).unarchived)
end
end
# if @universe_scope.present? && @content_type_class != Universe
# # Linkables cache is already scoped per-universe

# @content = @current_user_content.fetch(@content_type_class.name, [])
# .select { |page| page.universe_id == @universe_scope.id }

# @content = @universe_scope.send(pluralized_content_name)
# .includes(:page_tags, :image_uploads)
# .unarchived

# @show_scope_notice = true
# else
# @content = (
# current_user.send(pluralized_content_name).unarchived.includes(:page_tags, :image_uploads) +
# current_user.send("contributable_#{pluralized_content_name}").unarchived.includes(:page_tags, :image_uploads)
# )

@content = @content.to_a.flatten.uniq
# if @content_type_class != Universe
# my_universe_ids = current_user.universes.pluck(:id)
# @content.concat(@content_type_class.where(universe_id: my_universe_ids).unarchived)
# end
# end
# @content = @content.to_a.flatten.uniq

# Filters
@page_tags = PageTag.where(
Expand Down
32 changes: 31 additions & 1 deletion app/models/concerns/has_content.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,46 @@ module HasContent
has_many :attribute_categories
has_many :attribute_values, class_name: 'Attribute', dependent: :destroy

def content_with_multiple_queries(
content_types: Rails.application.config.content_type_names[:all],
page_scoping: { user_id: self.id },
universe_id: nil
)
@content_by_page_type = {}
content_types.each do |content_type|
type_specific_fields = ContentPage.polymorphic_content_fields
type_specific_fields.push 'universe_id' unless content_type == 'Universe'

pages_of_this_type = content_type.constantize
.where(page_scoping)
.select(type_specific_fields)

if content_type != 'Universe' && universe_id.present?
pages_of_this_type = pages_of_this_type.where(universe_id: universe_id)
end

@content_by_page_type[content_type] = []
pages_of_this_type.each do |page_data|
@content_by_page_type[content_type].push ContentPage.new(page_data.attributes)
end
end

@content_by_page_type
end

# {
# characters: [...],
# locations: [...]
# }
def content(
content_types: Rails.application.config.content_types[:all].map(&:name),
content_types: Rails.application.config.content_type_names[:all],
page_scoping: { user_id: self.id },
universe_id: nil
)
return content_with_multiple_queries(content_types: content_types, page_scoping: page_scoping, universe_id: universe_id)

return {} if content_types.empty?
# TODO: we should return early if we already have @content_by_page_type!!!

polymorphic_content_fields = ContentPage.polymorphic_content_fields
where_conditions = page_scoping.map { |key, value| "#{key} = #{value}" }.join(' AND ') + ' AND deleted_at IS NULL AND archived_at IS NULL'
Expand Down
15 changes: 15 additions & 0 deletions app/models/page_types/content_page.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
class ContentPage < ApplicationRecord
include Rails.application.routes.url_helpers

belongs_to :user
belongs_to :universe

attr_accessor :favorite

include Authority::Abilities
self.authorizer_name = 'ContentPageAuthorizer'

def random_image_including_private(format: :small)
ImageUpload.where(content_type: self.page_type, content_id: self.id).sample.try(:src, format) || "card-headers/#{self.page_type.downcase.pluralize}.jpg"
end
Expand All @@ -23,6 +30,14 @@ def favorite?
end

def view_path
send("#{self.page_type.downcase}_path", self.id)
end

def edit_path
send("edit_#{self.page_type.downcase}_path", self.id)
end

def self.polymorphic_content_fields
[:id, :name, :favorite, :page_type, :user_id, :created_at, :updated_at, :deleted_at, :archived_at, :privacy]
end
end
6 changes: 5 additions & 1 deletion app/services/permission_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ def self.content_is_in_a_public_universe?(content:)
def self.user_can_contribute_to_containing_universe?(user:, content:)
return false if user.nil?
return true if [AttributeCategory, AttributeField, Attribute].include?(content.class) #todo audit this
content.universe.present? && user.contributable_universes.pluck(:id).include?(content.universe.id)

return true if user.contributable_universe_ids.include?(content.universe_id)
return true if user.universes.pluck(:id).include?(content.universe_id)

return false
end

def self.content_has_no_containing_universe?(content:)
Expand Down
13 changes: 3 additions & 10 deletions app/views/content/list/_cards.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@
<div class="hoverable card sticky-action" style="margin-bottom: 2px">
<div class="card-image waves-effect waves-block waves-light">
<%= render partial: 'content/display/favorite_control', locals: { content: content } %>
<% content_image = asset_path("card-headers/#{content_type.name.downcase.pluralize}.jpg") %>
<% if content.respond_to?(:image_uploads) %>
<% images = content.image_uploads %>
<% if images.any? %>
<% content_image = images.sample.src(:medium) %>
<% end %>
<% end %>
<div class="activator" style="height: 265px; background: url('<%= content_image %>'); background-size: cover;"></div>
<div class="activator" style="height: 265px; background: url('<%= content.random_image_including_private(format: :medium) %>'); background-size: cover;"></div>

<span class="card-title js-content-name activator">
<div class="bordered-text">
Expand All @@ -35,13 +28,13 @@
</div>
<div class="card-action">
<% if current_user.can_update?(content) %>
<%= link_to edit_polymorphic_path(content), class: 'green-text right', target: content.is_a?(Document) ? '_new' : '_self' do %>
<%= link_to content.edit_path, class: 'green-text right', target: content.is_a?(Document) ? '_new' : '_self' do %>
<i class="material-icons left"><%= content_type.icon %></i>
Edit
<% end %>
<% end %>
<% if current_user.can_read?(content) %>
<%= link_to polymorphic_path(content), class: 'blue-text text-lighten-1' do %>
<%= link_to content.view_path, class: 'blue-text text-lighten-1' do %>
<i class="material-icons left"><%= content_type.icon %></i>
View
<% end %>
Expand Down