Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow strings as enum values #444

Merged
merged 9 commits into from
Oct 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ appraise 'activerecord_5.1.0' do
end
end

appraise 'activerecord_5.2.0' do
gem 'activerecord', '~> 5.2.0', require: 'active_record'
gem 'activesupport', '~> 5.2.0', require: 'active_support/all'
gem 'actionpack', '~> 5.2.0', require: 'action_pack'
appraise 'activerecord_5.2.1' do
gem 'activerecord', '~> 5.2.1', require: 'active_record'
gem 'activesupport', '~> 5.2.1', require: 'active_support/all'
gem 'actionpack', '~> 5.2.1', require: 'action_pack'

gemfile.platforms :jruby do
gem 'activerecord-jdbcsqlite3-adapter'
Expand Down
19 changes: 19 additions & 0 deletions gemfiles/activerecord_5.2.1.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "activerecord", "~> 5.2.1", require: "active_record"
gem "activesupport", "~> 5.2.1", require: "active_support/all"
gem "actionpack", "~> 5.2.1", require: "action_pack"

platforms :jruby do
gem "activerecord-jdbcsqlite3-adapter"
gem "jdbc-sqlite3"
end

platforms :ruby, :mswin, :mingw do
gem "sqlite3"
gem "pg", "~> 0.21"
end

gemspec path: "../"
25 changes: 6 additions & 19 deletions lib/cancan/model_adapters/active_record_5_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,12 @@ def self.matches_condition?(subject, name, value)
return super if Array.wrap(value).all? { |x| x.is_a? Integer }

attribute = subject.send(name)
if value.is_a?(Enumerable)
value.map(&:to_s).include? attribute
else
attribute == value.to_s
end
raw_attribute = subject.class.send(name.to_s.pluralize)[attribute]
!(Array(value).map(&:to_s) & [attribute, raw_attribute]).empty?
end

private

# As of rails 4, `includes()` no longer causes active record to
# look inside the where clause to decide to outer join tables
# you're using in the where. Instead, `references()` is required
# in addition to `includes()` to force the outer join.
def build_relation(*where_conditions)
relation = @model_class.where(*where_conditions)
relation = relation.includes(joins).references(joins) if joins.present?
relation
end

# Rails 4.2 deprecates `sanitize_sql_hash_for_conditions`
def sanitize_sql(conditions)
if conditions.is_a?(Hash)
sanitize_sql_activerecord5(conditions)
Expand All @@ -50,9 +36,10 @@ def sanitize_sql_activerecord5(conditions)

conditions.stringify_keys!

predicate_builder.build_from_hash(conditions).map do |b|
visit_nodes(b)
end.join(' AND ')
predicate_builder
.build_from_hash(conditions)
.map { |b| visit_nodes(b) }
.join(' AND ')
end

def visit_nodes(b)
Expand Down
42 changes: 42 additions & 0 deletions spec/cancan/model_adapters/active_record_5_adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,48 @@ class Shape < ActiveRecord::Base
expect(accessible).to contain_exactly(red, blue)
end

it 'allows strings as enum values' do
ActiveRecord::Schema.define do
create_table(:things) do |t|
t.string :size, default: 'big', null: false
end
end

class Thing < ActiveRecord::Base
enum size: { big: 'big', medium: 'average', small: 'small' }
end

big = Thing.create!(size: :big)
medium = Thing.create!(size: :medium)
small = Thing.create!(size: :small)

# A condition with a single value.
@ability.can :read, Thing, size: :medium

expect(@ability.cannot?(:read, big)).to be true
expect(@ability.can?(:read, medium)).to be true
expect(@ability.cannot?(:read, small)).to be true

accessible = Thing.accessible_by(@ability)
expect(accessible).to contain_exactly(medium)

@ability.cannot :read, Thing, size: 'average' # should undo previous rule
expect(@ability.can?(:read, medium)).to be false

accessible = Thing.accessible_by(@ability)
expect(accessible).to be_empty

# A condition with multiple values.
@ability.can :update, Thing, size: %i[big small]

expect(@ability.can?(:update, big)).to be true
expect(@ability.cannot?(:update, medium)).to be true
expect(@ability.can?(:update, small)).to be true

accessible = Thing.accessible_by(@ability, :update)
expect(accessible).to contain_exactly(big, small)
end

it 'allows dual filter on enums' do
ActiveRecord::Schema.define do
create_table(:discs) do |t|
Expand Down