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

Prevent normalization of polymorphic association #592

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
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