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

Fix healer when model uses an ordering default scope #27

Merged
merged 3 commits into from
Dec 3, 2024

Conversation

LukasSkywalker
Copy link
Contributor

When using an ordering default scope in the model, the query generated by the healer with model.select(*positioning_columns).distinct is invalid:

ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select
list (PG::InvalidColumnReference)

With a default scope that orders the records, Rails automatically adds the default scope to all queries, including the SELECT DISTINCT above. This breaks the healer, because it does not add the default ordering scope to the select list. Unscoping the query before selecting removes the default query and makes the healer work. This should not impact other functionality, since any ordering required when healing must be passed explicitely anyway.

Copy link
Owner

@brendon brendon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @LukasSkywalker, thanks for the PR. Just a few tweaks here. Let me know if you have any comments on any of them. I'm open minded :D

test/models/list.rb Outdated Show resolved Hide resolved
lib/positioning/healer.rb Outdated Show resolved Hide resolved
@LukasSkywalker LukasSkywalker force-pushed the main branch 2 times, most recently from 5589b21 to 30a59e9 Compare October 21, 2024 11:23
@@ -8,7 +8,7 @@ def initialize(model, column, order)

def heal
if positioning_columns.present?
@model.select(*positioning_columns).distinct.each do |scope_record|
@model.unscope(:order).select(*positioning_columns).distinct.each do |scope_record|
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we should also change select to reselect so that it blasts away any cases where people have a default scope involving select.

When using an ordering default scope in the model, the query generated by the
healer with `model.select(*positioning_columns).distinct` is invalid:

    ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select
    list (PG::InvalidColumnReference)

With a default scope that orders the records, Rails automatically adds the
default scope to all queries, including the SELECT DISTINCT above. This breaks
the healer, because it does not add the default ordering scope to the select
list. Unscoping the query before selecting removes the default query and makes
the healer work. This should not impact other functionality, since any ordering
required when healing must be passed explicitely anyway.
@model.select(*positioning_columns).distinct.each do |scope_record|
sequence @model.where(scope_record.slice(*positioning_columns))
@model.unscope(:select, :order).select(*positioning_columns).distinct.each do |scope_record|
sequence @model.unscope(:select).where(scope_record.slice(*positioning_columns))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brendon I changed the test case to include not only the order clause but also a select clause in the default scope. The tests only pass if I also undo the select on line 12 (in addition to 11), but I am unsure why this is needed.
If I understand the code correctly, the #sequence method takes a scope, overrides the ordering, and updates the position attribute. This should be independent of any select clause in the default scope, no?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a bit weird eh?! There won't even be a default scope of select to unscope. Did you try reselect instead of adding :select to the first unscope call?

@brendon
Copy link
Owner

brendon commented Nov 6, 2024

You'll need to rebase this as things have moved a bit in main. Can you also try using reselect and let's see how that tests out :)

@brendon
Copy link
Owner

brendon commented Nov 22, 2024

Hi @LukasSkywalker, do you still want to progress this?

@brendon brendon dismissed their stale review December 3, 2024 23:50

Not needed.

@brendon brendon merged commit b29b9ef into brendon:main Dec 3, 2024
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants