Permalink
Browse files

Merge branch 'squeel'

  • Loading branch information...
2 parents 5266613 + 32167b1 commit 9c079ae053da26d41a4586e3779d753025a9d2d8 Sijawusz Pur Rahnama committed May 4, 2012
Showing with 67 additions and 15 deletions.
  1. +1 −1 Gemfile
  2. +16 −0 lib/cancan.rb
  3. +43 −13 lib/cancan/model_adapters/active_record_adapter.rb
  4. +7 −1 lib/cancan/rule.rb
View
@@ -5,7 +5,7 @@ when nil, "active_record"
gem "sqlite3"
gem "activerecord", '~> 3.0.9', :require => "active_record"
gem "with_model", "~> 0.2.5"
- gem "meta_where"
+ gem "squeel", "~> 0.9.3"
when "data_mapper"
gem "dm-core", "~> 1.0.2"
gem "dm-sqlite-adapter", "~> 1.0.2"
View
@@ -11,3 +11,19 @@
require 'cancan/model_adapters/active_record_adapter' if defined? ActiveRecord
require 'cancan/model_adapters/data_mapper_adapter' if defined? DataMapper
require 'cancan/model_adapters/mongoid_adapter' if defined?(Mongoid) && defined?(Mongoid::Document)
+
+if defined? Squeel
+ class String
+ include Squeel::Nodes::PredicateOperators
+ end
+
+ module Squeel
+ module Visitors
+ class PredicateVisitor < Visitor
+ def visit_String(o, parent)
+ Arel::Nodes::SqlLiteral.new(o)
+ end
+ end
+ end
+ end
+end
@@ -6,21 +6,22 @@ def self.for_class?(model_class)
end
def self.override_condition_matching?(subject, name, value)
- name.kind_of?(MetaWhere::Column) if defined? MetaWhere
+ name.kind_of?(Squeel::Nodes::Predicate) if defined? Squeel
end
def self.matches_condition?(subject, name, value)
- subject_value = subject.send(name.column)
- if name.method.to_s.ends_with? "_any"
- value.any? { |v| meta_where_match? subject_value, name.method.to_s.sub("_any", ""), v }
- elsif name.method.to_s.ends_with? "_all"
- value.all? { |v| meta_where_match? subject_value, name.method.to_s.sub("_all", ""), v }
+ subject_value = subject.send(name.expr)
+ method_name = name.method_name.to_s
+ if method_name.ends_with? "_any"
+ value.any? { |v| squeel_match? subject_value, method_name.sub("_any", ""), v }
+ elsif method_name.ends_with? "_all"
+ value.all? { |v| squeel_match? subject_value, method_name.sub("_all", ""), v }
else
- meta_where_match? subject_value, name.method, value
+ squeel_match? subject_value, name.method_name, value
end
end
- def self.meta_where_match?(subject_value, method, value)
+ def self.squeel_match?(subject_value, method, value)
case method.to_sym
when :eq then subject_value == value
when :not_eq then subject_value != value
@@ -31,8 +32,8 @@ def self.meta_where_match?(subject_value, method, value)
when :gt then subject_value > value
when :gteq then subject_value >= value
when :matches then subject_value =~ Regexp.new("^" + Regexp.escape(value).gsub("%", ".*") + "$", true)
- when :does_not_match then !meta_where_match?(subject_value, :matches, value)
- else raise NotImplemented, "The #{method} MetaWhere condition is not supported."
+ when :does_not_match then !squeel_match?(subject_value, :matches, value)
+ else raise NotImplemented, "The #{method} Squeel condition is not supported."
end
end
@@ -54,14 +55,31 @@ def self.meta_where_match?(subject_value, method, value)
def conditions
if @rules.size == 1 && @rules.first.base_behavior
# Return the conditions directly if there's just one definition
- tableized_conditions(@rules.first.conditions).dup
+ tableized_conditions(unsqueeled_conditions(@rules.first.conditions.dup))
else
- @rules.reverse.inject(false_sql) do |sql, rule|
- merge_conditions(sql, tableized_conditions(rule.conditions).dup, rule.base_behavior)
+ @rules.reverse.inject(false_sql) do |accumulator, rule|
+ conditions = tableized_conditions(unsqueeled_conditions(rule.conditions.dup))
+ if conditions.blank?
+ rule.base_behavior ? (accumulator | true_sql) : (accumulator & false_sql)
+ else
+ rule.base_behavior ? (accumulator | conditions) : (accumulator & -conditions)
+ end
end
end
end
+ def unsqueeled_conditions(conditions)
+ return conditions unless conditions.kind_of? Hash
+ conditions.inject({}) do |result_hash, (name, value)|
+ name = name._name if name.is_a? Squeel::Nodes::Join
+ if value.kind_of? Hash
+ value = unsqueeled_conditions(value)
+ end
+ result_hash[name] = value
+ result_hash
+ end
+ end
+
def tableized_conditions(conditions, model_class = @model_class)
return conditions unless conditions.kind_of? Hash
conditions.inject({}) do |result_hash, (name, value)|
@@ -148,6 +166,18 @@ def merge_joins(base, add)
end
end
+ # override to fix overwrites
+ # do not write existing hashes using empty hashes
+ def merge_joins(base, add)
+ add.each do |name, nested|
+ if base[name].is_a?(Hash) && nested.present?
+ merge_joins(base[name], nested)
+ elsif !base[name].is_a?(Hash) || nested.present?
+ base[name] = nested
+ end
+ end
+ end
+
# Removes empty hashes and moves everything into arrays.
def clean_joins(joins_hash)
joins = []
View
@@ -108,7 +108,13 @@ def matches_conditions_hash?(subject, conditions = @conditions)
if model_adapter(subject).override_condition_matching? subject, name, value
model_adapter(subject).matches_condition? subject, name, value
else
- attribute = subject.send(name)
+ method_name = case name
+ when Symbol then name
+ when Squeel::Nodes::Join then name._name
+ when Squeel::Nodes::Predicate then name.expr
+ else raise name
+ end
+ attribute = subject.send(method_name)
if value.kind_of?(Hash)
if attribute.kind_of? Array
attribute.any? { |element| matches_conditions_hash? element, value }

0 comments on commit 9c079ae

Please sign in to comment.