From 9bee4a8d4b5bd9eb9569b9525f345e1ed511f51f Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Tue, 8 Mar 2011 23:19:56 -0800 Subject: [PATCH] adding any/all support for MetaWhere conditions --- .../model_adapters/active_record_adapter.rb | 18 ++++++++++++++---- .../active_record_adapter_spec.rb | 17 +++++++++++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/lib/cancan/model_adapters/active_record_adapter.rb b/lib/cancan/model_adapters/active_record_adapter.rb index f29696a..22fb669 100644 --- a/lib/cancan/model_adapters/active_record_adapter.rb +++ b/lib/cancan/model_adapters/active_record_adapter.rb @@ -11,7 +11,17 @@ module CanCan def self.matches_condition?(subject, name, value) subject_value = subject.send(name.column) - case name.method.to_sym + 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 } + else + meta_where_match? subject_value, name.method, value + end + end + + def self.meta_where_match?(subject_value, method, value) + case method.to_sym when :eq then subject_value == value when :not_eq then subject_value != value when :in then value.include?(subject_value) @@ -20,9 +30,9 @@ module CanCan when :lteq then subject_value <= value when :gt then subject_value > value when :gteq then subject_value >= value - when :matches then subject_value.downcase.include?(value.downcase) - when :does_not_match then !subject_value.downcase.include?(value.downcase) - else raise NotImplemented, "The #{name.method} MetaWhere condition is not supported." + 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." end end diff --git a/spec/cancan/model_adapters/active_record_adapter_spec.rb b/spec/cancan/model_adapters/active_record_adapter_spec.rb index db0fb18..21b61f9 100644 --- a/spec/cancan/model_adapters/active_record_adapter_spec.rb +++ b/spec/cancan/model_adapters/active_record_adapter_spec.rb @@ -231,6 +231,10 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record" article1 = Article.new(:priority => 1, :name => "Hello World") adapter.matches_condition?(article1, :priority.eq, 1).should be_true adapter.matches_condition?(article1, :priority.eq, 2).should be_false + adapter.matches_condition?(article1, :priority.eq_any, [1, 2]).should be_true + adapter.matches_condition?(article1, :priority.eq_any, [2, 3]).should be_false + adapter.matches_condition?(article1, :priority.eq_all, [1, 1]).should be_true + adapter.matches_condition?(article1, :priority.eq_all, [1, 2]).should be_false adapter.matches_condition?(article1, :priority.ne, 2).should be_true adapter.matches_condition?(article1, :priority.ne, 1).should be_false adapter.matches_condition?(article1, :priority.in, [1, 2]).should be_true @@ -245,10 +249,15 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record" adapter.matches_condition?(article1, :priority.gt, 1).should be_false adapter.matches_condition?(article1, :priority.gteq, 1).should be_true adapter.matches_condition?(article1, :priority.gteq, 2).should be_false - adapter.matches_condition?(article1, :name.like, "ello worl").should be_true - adapter.matches_condition?(article1, :name.like, "helo").should be_false - adapter.matches_condition?(article1, :name.nlike, "helo").should be_true - adapter.matches_condition?(article1, :name.nlike, "ello worl").should be_false + adapter.matches_condition?(article1, :name.like, "%ello worl%").should be_true + adapter.matches_condition?(article1, :name.like, "hello world").should be_true + adapter.matches_condition?(article1, :name.like, "hello%").should be_true + adapter.matches_condition?(article1, :name.like, "h%d").should be_true + adapter.matches_condition?(article1, :name.like, "%helo%").should be_false + adapter.matches_condition?(article1, :name.like, "hello").should be_false + adapter.matches_condition?(article1, :name.like, "hello.world").should be_false + adapter.matches_condition?(article1, :name.nlike, "%helo%").should be_true + adapter.matches_condition?(article1, :name.nlike, "%ello worl%").should be_false end end end