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 #979 Address crashes with three state boolean detection #980

Closed
wants to merge 2 commits into from

Conversation

doconnor-clintel
Copy link

Fix #979


Before submitting the PR make sure the following are checked:

  • The PR relates to only one subject with a clear title and description in grammatically correct, complete sentences.
  • Wrote good commit messages.
  • Commit message starts with [Fix #issue-number] (if the related issue exists).
  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Ran bundle exec rake default. It executes all tests and runs RuboCop on its own code.
  • Added an entry (file) to the changelog folder named {change_type}_{change_description}.md if the new code introduces user-observable changes. See changelog entry format for details.

@doconnor-clintel
Copy link
Author

Sorry folks, I don't have the capacity to test locally at the moment or fix the existing test coverage.

@@ -60,7 +63,7 @@ def table_node(node)
node.first_argument
when :column, :boolean
ancestor = node.each_ancestor(:block).find do |n|
n.method?(:create_table) || n.method?(:change_table)
n.method?(:create_table) || n.method?(:change_table) || n.method?(:drop_table) || n.method?(:create_enum)

Choose a reason for hiding this comment

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

create_enum was meant to be a representative example of a project-specific wrapper for create_table, and I don't think it's appropriate to add project-specific wrappers to a general purpose gem, unless it's via a configuration option.

What does adding drop_table do here? Can it take a block?

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Author

@doconnor-clintel doconnor-clintel Apr 11, 2023

Choose a reason for hiding this comment

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

Removed create_enum; though https://blog.saeloun.com/2022/01/12/rails-7-adds-custom-enum-support-in-postgresql is an addition in rails 7.

See rails/rails#41469 for where it was added to rails, and some of the other create_* methods that potentially should also be skipped by this check. Edit sorry, it's from your original bug report! So you know all that.

Copy link

Choose a reason for hiding this comment

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

To be clear, drop_table can take a block, it is used when rolling back the migration to recreate the table that was dropped.

@@ -46,6 +46,9 @@ def on_send(node)

def_node = node.each_ancestor(:def, :defs).first
table_node = table_node(node)

return unless table_node && column_node

Choose a reason for hiding this comment

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

The following line calling change_column_null?, I read as: "if we can find code that changes the column nullness later, then don't add a violation". But if that code can't be found, because there's no enclosing def block to search, then the exception can't be made, and it will report a violation, maybe causing a false positive.

To be consistent with the above, if it can't find the nullness change because other parts of the context are missing (like the table name), I think it should also skip the exception and report a violation.

Copy link
Author

Choose a reason for hiding this comment

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

Not 100% clear here, are you suggesting:

return if def_node && change_column_null?(def_node, table_node&.value, column_node&.value)

Or something else?

Choose a reason for hiding this comment

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

I think I would go with

return if def_node && table_node && column_node && \
  change_column_null?(def_node, table_node.value, column_node.value)

@koic
Copy link
Member

koic commented Apr 13, 2023

I'm going to close this PR because no one can do regression testing without a reproduction test. I opened #983 instead. Thank you.

@koic koic closed this Apr 13, 2023
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.

Rails/ThreeStateBoolean fails when it can't find create_table or change_table
4 participants