Created
March 1, 2012 18:38
-
-
Save the8472/1952018 to your computer and use it in GitHub Desktop.
Make CanCan 1.6 + arel 2.0 work with multiple scopes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "cancan/model_adapters/active_record_adapter" | |
class CanCan::ModelAdapters::ActiveRecordAdapter | |
# disable the error when multiple conditions with scopes are used | |
def override_scope | |
return false | |
end | |
# convert where-clauses from relations into sql strings which will be merged by the cancan merge_conditions logic | |
def tableized_conditions_with_relations(*args) | |
if args.first.kind_of?(ActiveRecord::Relation) | |
base_class = @model_class.unscoped | |
arel = args.first.arel | |
arel.where_clauses.join(" AND ") | |
else | |
tableized_conditions_without_relations(*args) | |
end | |
end | |
alias_method_chain :tableized_conditions, :relations unless method_defined? :tableized_conditions_without_relations | |
# convert join-clauses from relations into sql strings which will be merged by the cancan merge_joins logic | |
def joins_with_relations | |
arr = joins_without_relations || [] | |
arr.concat(@rules.map(&:conditions).select{|c| c.kind_of?(ActiveRecord::Relation)}.map do |rel| | |
arel = rel.arel | |
arel.ast.cores.each{|c| convert_join(c)} | |
arel.join_sql | |
end) | |
arr.delete_if{|e| e.blank?} | |
arr = nil if arr.empty? | |
arr | |
end | |
alias_method_chain :joins, :relations unless method_defined? :joins_without_relations | |
private | |
# helper that traverses a arel AST to turn inner into outer joins | |
def convert_join(ast) | |
ast.froms = convert_join(ast.froms) if ast.is_a? Arel::Nodes::SelectCore | |
if ast.is_a? Arel::Nodes::Join | |
ast.left = convert_join(ast.left) | |
ast.right = convert_join(ast.right) | |
end | |
return Arel::Nodes::OuterJoin.new(ast.left,ast.right,ast.constraint) if ast.is_a? Arel::Nodes::InnerJoin | |
ast | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment