You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I want to implement my own SQL strategy to fight some performance issues regarding subqueries and distinct keywords in the left_join strategy. My approach is, to skip the distinct as along as the all joins are belongs_to or has_one. This way, the query will run in 1/30 of the time on my system.
However, adding a custom strategy requires some monkey patching, which is quiet ugly:
# config/initializers/cancancan.rb
CanCan.module_eval do
class << self
alias _valid_accessible_by_strategies valid_accessible_by_strategies
def valid_accessible_by_strategies
_valid_accessible_by_strategies + [CanCanLeftJoinOptimizedWithFallback::STRATEGY_NAME]
end
end
end
Rails.configuration.to_prepare { CanCanLeftJoinOptimizedWithFallback.install }
# app/lib/can_can_left_join_optimized_with_fallback.rb
class CanCanLeftJoinOptimizedWithFallback < CanCan::ModelAdapters::Strategies::Base
STRATEGY_NAME = name.delete_prefix("CanCan").underscore.to_sym
class << self
def install
const = STRATEGY_NAME.to_s.camelize.to_sym
if CanCan::ModelAdapters::Strategies.const_defined?(const)
CanCan::ModelAdapters::Strategies.send(:remove_const, const)
end
CanCan::ModelAdapters::Strategies.const_set(const, self)
CanCan.accessible_by_strategy = STRATEGY_NAME
end
end
def execute!
# ...
end
end
Expected behavior
It would be nice to add a custom strategy like this:
Rails.configuration.to_prepare do
CanCan.accessible_by_strategy = CanCanLeftJoinOptimizedWithFallback
end
The setter could recognize if the argument is a class or a symbol and add it to the allowed strategies. It would also have to be compatible with Zeitwerks, so when the to_prepare hook from Rails is triggered during development, the constant is removed and added again like I do in my .install method.
I'll be happy to try for a PR, but I would need some guidance on how this could be implemented.
Actual behavior
> CanCan.accessible_by_strategy = CanCanLeftJoinOptimizedWithFallback
ArgumentError: accessible_by_strategy must be one of left_join, joined_alias_exists_subquery, joined_alias_each_rule_as_exists_subquery, subquery
System configuration
Rails version:
7.0.8.1
Ruby version:
3.2.1
CanCanCan version
3.5.0
The text was updated successfully, but these errors were encountered:
Steps to reproduce
I want to implement my own SQL strategy to fight some performance issues regarding subqueries and distinct keywords in the left_join strategy. My approach is, to skip the distinct as along as the all joins are belongs_to or has_one. This way, the query will run in 1/30 of the time on my system.
However, adding a custom strategy requires some monkey patching, which is quiet ugly:
Expected behavior
It would be nice to add a custom strategy like this:
The setter could recognize if the argument is a class or a symbol and add it to the allowed strategies. It would also have to be compatible with Zeitwerks, so when the to_prepare hook from Rails is triggered during development, the constant is removed and added again like I do in my
.install
method.I'll be happy to try for a PR, but I would need some guidance on how this could be implemented.
Actual behavior
System configuration
Rails version:
7.0.8.1
Ruby version:
3.2.1
CanCanCan version
3.5.0
The text was updated successfully, but these errors were encountered: