Skip to content

Instantly share code, notes, and snippets.

@the8472
Created March 1, 2012 18:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save the8472/1952018 to your computer and use it in GitHub Desktop.
Save the8472/1952018 to your computer and use it in GitHub Desktop.
Make CanCan 1.6 + arel 2.0 work with multiple scopes
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