Skip to content

Commit

Permalink
Convert enum values to integers during comparison
Browse files Browse the repository at this point in the history
Fixes Issue CanCanCommunity#102.
  • Loading branch information
markpmitchell committed Apr 1, 2015
1 parent 7a9915b commit 8112b03
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
15 changes: 15 additions & 0 deletions lib/cancan/model_adapters/active_record_4_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ def build_relation(*where_conditions)
relation
end

def self.override_condition_matching?(subject, name, value)
subject.class.defined_enums.include? name.to_s
end

def self.matches_condition?(subject, name, value)
# Get the mapping from enum strings to values.
enum = subject.class.send(name.to_s.pluralize)
# Get the value of the attribute as an integer.
attribute = enum[subject.send(name)]
# Check to see if the value matches the condition.
value.is_a?(Enumerable) ?
(value.include? attribute) :
attribute == value
end

# Rails 4.2 deprecates `sanitize_sql_hash_for_conditions`
def sanitize_sql(conditions)
if ActiveRecord::VERSION::MINOR >= 2 && Hash === conditions
Expand Down
37 changes: 37 additions & 0 deletions spec/cancan/model_adapters/active_record_4_adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,43 @@ class Child < ActiveRecord::Base

expect(Parent.accessible_by(@ability).order(:created_at => :asc).includes(:children).first.children).to eq [child2, child1]
end

it "allows filters on enums" do
ActiveRecord::Schema.define do
create_table(:shapes) do |t|
t.integer :color, default: 0, null: false
end
end

class Shape < ActiveRecord::Base
enum color: [:red, :green, :blue]
end

red = Shape.create!(color: :red)
green = Shape.create!(color: :green)
blue = Shape.create!(color: :blue)

# A condition with a single value.
@ability.can :read, Shape, color: Shape.colors[:green]

expect(@ability.cannot? :read, red).to be true
expect(@ability.can? :read, green).to be true
expect(@ability.cannot? :read, blue).to be true

accessible = Shape.accessible_by(@ability)
expect(accessible).to contain_exactly(green)

# A condition with multiple values.
@ability.can :update, Shape, color: [Shape.colors[:red],
Shape.colors[:blue]]

expect(@ability.can? :update, red).to be true
expect(@ability.cannot? :update, green).to be true
expect(@ability.can? :update, blue).to be true

accessible = Shape.accessible_by(@ability, :update)
expect(accessible).to contain_exactly(red, blue)
end
end

if Gem::Specification.find_all_by_name('pg').any?
Expand Down

0 comments on commit 8112b03

Please sign in to comment.