Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport optimize performance #359

Open
wants to merge 7 commits into
base: release/0.27-stable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ module ProposalMCellOverride
alias_method :decidim_original_cache_hash, :cache_hash

def cache_hash
extra_hash = model.extra_fields&.reload&.vote_weight_totals
"#{decidim_original_cache_hash}#{Decidim.cache_key_separator}#{extra_hash}"
all_extra_fields = memoize("extra_fields")
extra_fields = all_extra_fields ? all_extra_fields[model.id] : model.extra_fields

@cache_hash ||= "#{decidim_original_cache_hash}#{Decidim.cache_key_separator}#{extra_fields&.vote_weight_totals}"
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,27 @@ def component_settings
end

def current_vote
@current_vote ||= Decidim::Proposals::ProposalVote.find_by(author: current_user, proposal: model)
@current_vote ||= vote_for(current_user) if current_user
end

def user_voted_weight
current_vote&.weight
end

def vote_for(user)
user_votes = memoize("user_votes")
return user_votes[model.id] if user_votes

model.votes.find_by(author: user)
end

def weight_count_for(weight)
all_extra_fields = memoize("extra_fields")
extra_fields = all_extra_fields ? all_extra_fields[model.id] : model.extra_fields
return 0 unless extra_fields

extra_fields.vote_weight_totals[weight.to_s] || 0
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<% unless proposal.rejected? || proposal.withdrawn? %>
<% unless current_settings.votes_hidden? %>
<span class="votes_counter">
<span data-weight="3" title="<%= proposal.manifest.label_for(3) %>" class="weight_3"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_3_short") %> <%= model.weight_count(3) %></span> |
<span data-weight="2" title="<%= proposal.manifest.label_for(2) %>" class="weight_2"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_2_short") %> <%= model.weight_count(2) %></span> |
<span data-weight="1" title="<%= proposal.manifest.label_for(1) %>" class="weight_1"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_1_short") %> <%= model.weight_count(1) %></span>
<span data-weight="3" title="<%= proposal.manifest.label_for(3) %>" class="weight_3"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_3_short") %> <%= weight_count_for(3) %></span> |
<span data-weight="2" title="<%= proposal.manifest.label_for(2) %>" class="weight_2"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_2_short") %> <%= weight_count_for(2) %></span> |
<span data-weight="1" title="<%= proposal.manifest.label_for(1) %>" class="weight_1"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_1_short") %> <%= weight_count_for(1) %></span>
<% if current_component.settings.voting_cards_show_abstain %>
| <span title="<%= proposal.manifest.label_for(0) %>" data-weight="0" class="weight_0"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_0_short") %> <%= model.weight_count(0) %></span>
| <span title="<%= proposal.manifest.label_for(0) %>" data-weight="0" class="weight_0"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_0_short") %> <%= weight_count_for(0) %></span>
<% end %>
</span>
<% end %>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div id="vote-container" data-proposal-id="<%= proposal.id %>">
<div class="vote-block">
<% unless current_settings.votes_hidden? %>
<p class="vote-count" data-weight="<%= weight %>"><%= proposal_votes(weight) %></p>
<p class="vote-count" data-weight="<%= weight %>"><%= weight_count_for(weight) %></p>
<% end %>
<%= action_authorized_link_to :vote,
proposal_vote_path(weight),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ def vote_block_for(proposal, weight)
}
end

def proposal_votes(weight)
model.weight_count(weight)
end

def voted_for?(option)
user_voted_weight == option
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "decidim/decidim_awesome/awesome_helpers"

module Decidim
module DecidimAwesome
module NeedsAwesomeConfig
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module Decidim
module DecidimAwesome
module Proposals
module MemoizeExtraFields
extend ActiveSupport::Concern
include Decidim::DecidimAwesome::RequestMemoizer

included do
alias_method :decidim_original_index, :index

def index
decidim_original_index

memoize("extra_fields") { Decidim::DecidimAwesome::ProposalExtraField.where(proposal: @proposals).index_by(&:decidim_proposal_id) }
memoize("user_votes") { Decidim::Proposals::ProposalVote.where(proposal: proposals, author: current_user).index_by(&:decidim_proposal_id) if current_user }
end
end
end
end
end
end
2 changes: 2 additions & 0 deletions lib/decidim/decidim_awesome/awesome.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Decidim
module DecidimAwesome
include ActiveSupport::Configurable

autoload :AwesomeHelpers, "decidim/decidim_awesome/awesome_helpers"
autoload :RequestMemoizer, "decidim/decidim_awesome/request_memoizer"
autoload :Config, "decidim/decidim_awesome/config"
autoload :SystemChecker, "decidim/decidim_awesome/system_checker"
autoload :ContextAnalyzers, "decidim/decidim_awesome/context_analyzers"
Expand Down
63 changes: 40 additions & 23 deletions lib/decidim/decidim_awesome/awesome_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,28 @@ module Decidim
# add a global helper with awesome configuration
module DecidimAwesome
module AwesomeHelpers
include RequestMemoizer

# Returns the normalized config for an Organization and the current url
def awesome_config_instance
return @awesome_config_instance if @awesome_config_instance

# if already created in the middleware, reuse it as it might have additional constraints
@awesome_config_instance = request.env["decidim_awesome.current_config"]
unless @awesome_config_instance.is_a? Config
@awesome_config_instance = Config.new request.env["decidim.current_organization"]
@awesome_config_instance.context_from_request request
memoize("current_config") do
config = Config.new(request.env["decidim.current_organization"])
config.context_from_request(request)
config
end
@awesome_config_instance
end

def awesome_config
@awesome_config ||= awesome_config_instance.config
memoize("awesome_config") do
awesome_config_instance.config
end
end

def javascript_config_vars
awesome_config.slice(:allow_images_in_proposals, :allow_images_in_small_editor, :allow_images_in_full_editor, :allow_images_in_markdown_editor, :use_markdown_editor,
:auto_save_forms).to_json.html_safe
memoize("javascript_config_vars") do
awesome_config.slice(:allow_images_in_proposals, :allow_images_in_small_editor, :allow_images_in_full_editor, :allow_images_in_markdown_editor, :use_markdown_editor,
:auto_save_forms).to_json.html_safe
end
end

def show_public_intergram?
Expand All @@ -36,11 +38,15 @@ def show_public_intergram?
end

def unfiltered_awesome_config
@unfiltered_awesome_config ||= awesome_config_instance.unfiltered_config
memoize("unfiltered_awesome_config") do
awesome_config_instance.unfiltered_config
end
end

def organization_awesome_config
@organization_awesome_config ||= awesome_config_instance.organization_config
memoize("organization_awesome_config") do
awesome_config_instance.organization_config
end
end

def awesome_version
Expand All @@ -49,40 +55,51 @@ def awesome_version

# Collects all CSS that is applied in the current URL context
def awesome_scoped_styles
@awesome_scoped_styles ||= awesome_config_instance.collect_sub_configs_values("scoped_style")
memoize("awesome_scoped_styles") do
awesome_config_instance.collect_sub_configs_values("scoped_style")
end
end

# Collects all CSS that is applied in the current URL context
def awesome_scoped_admin_styles
@awesome_scoped_admin_styles ||= awesome_config_instance.collect_sub_configs_values("scoped_admin_style")
memoize("awesome_scoped_admin_styles") do
awesome_config_instance.collect_sub_configs_values("scoped_admin_style")
end
end

# Collects all proposal custom fields that is applied in the current URL context
def awesome_scoped_admins
@awesome_scoped_admins ||= awesome_config_instance.collect_sub_configs_values("scoped_admin")
memoize("awesome_scoped_admins") do
awesome_config_instance.collect_sub_configs_values("scoped_admin")
end
end

# Collects all proposal custom fields that is applied in the current URL context
def awesome_proposal_custom_fields
@awesome_proposal_custom_fields ||= awesome_config_instance.collect_sub_configs_values("proposal_custom_field")
memoize("awesome_proposal_custom_fields") do
awesome_config_instance.collect_sub_configs_values("proposal_custom_field")
end
end

def awesome_proposal_private_custom_fields
@awesome_proposal_private_custom_fields ||= awesome_config_instance.collect_sub_configs_values("proposal_private_custom_field")
memoize("awesome_proposal_private_custom_fields") do
awesome_config_instance.collect_sub_configs_values("proposal_private_custom_field")
end
end

# this will check if the current component has been configured to use a custom voting manifest
def awesome_voting_manifest_for(component)
return nil unless component.settings.respond_to? :awesome_voting_manifest

DecidimAwesome.voting_registry.find(component.settings.awesome_voting_manifest)
memoize("awesome_voting_manifest_for_#{component.id}") do
DecidimAwesome.voting_registry.find(component.settings.try(:awesome_voting_manifest))
end
end

# Retrives all the "admins_available_authorizations" for the user along with other possible authorizations
# returns an instance of Decidim::DecidimAwesome::Authorizator
def awesome_authorizations_for(user)
@awesome_authorizations_for ||= {}
@awesome_authorizations_for[user.id] ||= Authorizator.new(user, awesome_config[:admins_available_authorizations])
memoize("awesome_authorizations_for_#{user.id}") do
Authorizator.new(user, awesome_config[:admins_available_authorizations])
end
end

def version_prefix
Expand Down
5 changes: 1 addition & 4 deletions lib/decidim/decidim_awesome/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ class Engine < ::Rails::Engine
# https://edgeguides.rubyonrails.org/engines.html#overriding-models-and-controllers
# overrides
config.to_prepare do
# activate Decidim LayoutHelper for the overriden views
ActiveSupport.on_load :action_controller do
helper Decidim::LayoutHelper if respond_to?(:helper)
end
# Include additional helpers globally
ActiveSupport.on_load(:action_view) { include Decidim::DecidimAwesome::AwesomeHelpers }
# Also for cells
Expand Down Expand Up @@ -123,6 +119,7 @@ class Engine < ::Rails::Engine
end

if DecidimAwesome.enabled?(:weighted_proposal_voting)
Decidim::Proposals::ProposalsController.include(Decidim::DecidimAwesome::Proposals::MemoizeExtraFields)
Decidim::Proposals::ProposalVotesController.include(Decidim::DecidimAwesome::Proposals::ProposalVotesControllerOverride)
end

Expand Down
1 change: 1 addition & 0 deletions lib/decidim/decidim_awesome/organization_memoizer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

16 changes: 16 additions & 0 deletions lib/decidim/decidim_awesome/request_memoizer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module Decidim
module DecidimAwesome
module RequestMemoizer
# memoize a piece of code in the global request instead of the helper instance (helpers are initialized for each view)
def memoize(key)
if defined?(request) && request.env["decidim.current_organization"]&.id
request.env["decidim_awesome.#{key}"] ||= block_given? ? yield : nil
elsif block_given?
yield
end
end
end
end
end
8 changes: 4 additions & 4 deletions spec/cells/voting/voting_cards_proposal_cell_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ module Voting
]
end

describe "#proposal_votes" do
describe "#weight_count_for" do
it "returns the correct number of votes for a given weight" do
expect(subject.proposal_votes(1)).to eq(3)
expect(subject.proposal_votes(2)).to eq(2)
expect(subject.proposal_votes(3)).to eq(1)
expect(subject.weight_count_for(1)).to eq(3)
expect(subject.weight_count_for(2)).to eq(2)
expect(subject.weight_count_for(3)).to eq(1)
end
end

Expand Down
Loading