diff --git a/lib/cancan/ability.rb b/lib/cancan/ability.rb index 535663e..b20c0f1 100644 --- a/lib/cancan/ability.rb +++ b/lib/cancan/ability.rb @@ -190,11 +190,11 @@ module CanCan # If the ability is not defined then false is returned so be sure to take that into consideration. # If the ability is defined using a block then this will raise an exception since a hash of conditions cannot be # determined from that. - def conditions(action, subject) + def conditions(action, subject, options = {}) can_definition = matching_can_definition(action, subject) if can_definition raise Error, "Cannot determine ability conditions from block for #{action.inspect} #{subject.inspect}" if can_definition.block - can_definition.conditions || {} + can_definition.conditions(options) || {} else false end diff --git a/lib/cancan/active_record_additions.rb b/lib/cancan/active_record_additions.rb index 2afa33d..e5bda3b 100644 --- a/lib/cancan/active_record_additions.rb +++ b/lib/cancan/active_record_additions.rb @@ -20,7 +20,7 @@ module CanCan # Here only the articles which the user can update are returned. This # internally uses Ability#conditions method, see that for more information. def accessible_by(ability, action = :read) - conditions = ability.conditions(action, self) || {:id => nil} + conditions = ability.conditions(action, self, :tableize => true) || {:id => nil} joins = ability.association_joins(action, self) if respond_to? :where where(conditions).joins(joins) diff --git a/lib/cancan/can_definition.rb b/lib/cancan/can_definition.rb index 9b3b945..c1dce1e 100644 --- a/lib/cancan/can_definition.rb +++ b/lib/cancan/can_definition.rb @@ -1,7 +1,8 @@ module CanCan # This class is used internally and should only be called through Ability. class CanDefinition # :nodoc: - attr_reader :conditions, :block + include ActiveSupport::Inflector + attr_reader :block def initialize(base_behavior, action, subject, conditions, block) @base_behavior = base_behavior @@ -25,6 +26,19 @@ module CanCan result = can_without_base_behavior?(action, subject, extra_args) @base_behavior ? result : !result end + + def conditions(options = {}) + if options[:tableize] and @conditions.kind_of? Hash + @conditions.inject({}) do |tableized_conditions, (name, value)| + name = tableize(name).to_sym if value.kind_of? Hash + + tableized_conditions[name] = value + tableized_conditions + end + else + @conditions + end + end def association_joins(conditions = @conditions) joins = [] diff --git a/spec/cancan/active_record_additions_spec.rb b/spec/cancan/active_record_additions_spec.rb index 640f44a..41aaf3c 100644 --- a/spec/cancan/active_record_additions_spec.rb +++ b/spec/cancan/active_record_additions_spec.rb @@ -16,13 +16,13 @@ describe CanCan::ActiveRecordAdditions do it "should call where with matching ability conditions" do @ability.can :read, @model_class, :foo => {:bar => 1} - stub(@model_class).where(:foo => { :bar => 1 }).stub!.joins([:foo]) { :found_records } + stub(@model_class).where(:foos => { :bar => 1 }).stub!.joins([:foo]) { :found_records } @model_class.accessible_by(@ability, :read).should == :found_records end it "should default to :read ability and use scoped when where isn't available" do @ability.can :read, @model_class, :foo => {:bar => 1} - stub(@model_class).scoped(:conditions => {:foo => {:bar => 1}}, :joins => [:foo]) { :found_records } + stub(@model_class).scoped(:conditions => {:foos => {:bar => 1}}, :joins => [:foo]) { :found_records } @model_class.accessible_by(@ability).should == :found_records end end diff --git a/spec/cancan/can_definition_spec.rb b/spec/cancan/can_definition_spec.rb index 697dc74..c9f7633 100644 --- a/spec/cancan/can_definition_spec.rb +++ b/spec/cancan/can_definition_spec.rb @@ -30,4 +30,10 @@ describe CanCan::CanDefinition do @conditions[:foo] = {:bar => {1 => 2}} @can.association_joins.should == [{:foo => [:bar]}] end + + it "should return table names in conditions for association joins" do + @conditions[:foo] = {:bar => 1} + @conditions[:test] = 1 + @can.conditions(:tableize => true).should == { :foos => { :bar => 1}, :test => 1 } + end end