Skip to content

Commit

Permalink
Prevent normalization of polymorphic association
Browse files Browse the repository at this point in the history
Polymorphic associations have no klass names, so those should be not
normalized. Fixes #588.

Add tests using an action_storage like schema and add changelog entry.
  • Loading branch information
eloyesp committed Aug 7, 2019
1 parent 842251e commit 159e752
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
* [#592](https://github.com/CanCanCommunity/cancancan/pull/592): Prevent normalization of through polymorphic associations.([@eloyesp][])

## 3.0.1

* [#583](https://github.com/CanCanCommunity/cancancan/pull/583): Fix regression when using a method reference block. ([@coorasse][])
Expand Down Expand Up @@ -643,3 +645,4 @@ Please read the [guide on migrating from CanCanCan 2.x to 3.0](https://github.co
[@andrew-aladev]: https://github.com/andrew-aladev
[@phaedryx]: https://github.com/phaedryx
[@kaspernj]: https://github.com/kaspernj
[@eloyesp]: https://github.com/eloyesp
6 changes: 5 additions & 1 deletion lib/cancan/model_adapters/conditions_normalizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,18 @@ def calculate_result_hash(model_class, key, value)
raise WrongAssociationName, "Association '#{key}' not defined in model '#{model_class.name}'"
end

if reflection.options[:through].present?
if normalizable_association? reflection
key = reflection.options[:through]
value = { reflection.source_reflection_name => value }
reflection = model_class.reflect_on_association(key)
end

{ key => normalize_conditions(reflection.klass.name.constantize, value) }
end

def normalizable_association?(reflection)
reflection.options[:through].present? && !reflection.options[:source_type].present?
end
end
end
end
Expand Down
25 changes: 25 additions & 0 deletions spec/cancan/model_adapters/conditions_normalizer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,22 @@
t.integer :user_id
t.integer :article_id
end

create_table(:attachments) do |t|
t.references :record, polymorphic: true
t.integer :blob_id
end

create_table(:blob) do |t|
end
end

class Article < ActiveRecord::Base
has_many :spread_comments
has_many :comments, through: :spread_comments
has_many :mentions
has_many :mentioned_users, through: :mentions, source: :user
has_many :attachments, as: :record
end

class Comment < ActiveRecord::Base
Expand All @@ -53,6 +62,16 @@ class User < ActiveRecord::Base
has_many :mentions
has_many :mentioned_articles, through: :mentions, source: :article
end

class Attachment < ActiveRecord::Base
belongs_to :record, polymorphic: true
belongs_to :blob
end

class Blob < ActiveRecord::Base
has_many :attachments
has_many :articles, through: :attachments, source: :record, source_type: 'Article'
end
end

it 'simplifies has_many through associations' do
Expand All @@ -61,6 +80,12 @@ class User < ActiveRecord::Base
expect(rule.conditions).to eq(spread_comments: { article: { mentions: { user: { name: 'pippo' } } } })
end

it 'does not simplifies has_many through polymorphic associations' do
rule = CanCan::Rule.new(true, :read, Blob, articles: { id: 11 })
CanCan::ModelAdapters::ConditionsNormalizer.normalize(Blob, [rule])
expect(rule.conditions).to eq(articles: { id: 11 })
end

it 'normalizes the has_one through associations' do
class Supplier < ActiveRecord::Base
has_one :accountant
Expand Down

0 comments on commit 159e752

Please sign in to comment.