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

Action Order Cop #547

Merged
merged 1 commit into from
Oct 6, 2022
Merged

Action Order Cop #547

merged 1 commit into from
Oct 6, 2022

Conversation

mollerhoj
Copy link
Contributor

@mollerhoj mollerhoj commented Sep 13, 2021

Please excuse any obvious mistakes, this is my first cop.

Fix #540

Copy link
Member

@dvandersluis dvandersluis left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! This is missing a few required things, including tests, a changelog entry, adding a require to https://github.com/rubocop/rubocop-rails/blob/master/lib/rubocop/cop/rails_cops.rb, adding an entry for this cop to https://github.com/rubocop/rubocop-rails/blob/master/config/default.yml.

CHANGELOG.md Outdated Show resolved Hide resolved
config/default.yml Outdated Show resolved Hide resolved
@mollerhoj mollerhoj force-pushed the action-order-cop branch 2 times, most recently from cfce285 to 2103106 Compare September 13, 2021 16:49
@dvandersluis
Copy link
Member

Thanks for making the changes I requested. Looks good at this point, but still requires tests in order to be merged.

config/default.yml Outdated Show resolved Hide resolved
@dvandersluis dvandersluis dismissed their stale review September 13, 2021 19:29

The missing elements I requested are there now.

@mollerhoj
Copy link
Contributor Author

mollerhoj commented Sep 13, 2021

Thanks for all your help guys.

I implemented autocorrection, but I feel like I have to try it on our codebase before I feel I can trust it.

Also, I don't know how to mark it as a safe/unsafe correction (-a vs -A) or which it should be marked as.

@andyw8
Copy link
Contributor

andyw8 commented Sep 13, 2021

The only way I can think of that would be unsafe is if someone had accidentally defined the same method twice in a controller, so that only the later one was in use. Then re-ordering might change the behaviour.

@mollerhoj
Copy link
Contributor Author

The only way I can think of that would be unsafe is if someone had accidentally defined the same method twice in a controller, so that only the later one was in use. Then re-ordering might change the behaviour.

Heh yeah, so it comes down to the significance of -A vs. -a I guess -a should never ever have any opportunity to go wrong, so we have to stick to -A because of this strange edgecase?

@andyw8
Copy link
Contributor

andyw8 commented Sep 13, 2021

Heh yeah, so it comes down to the significance of -A vs. -a I guess -a should never ever have any opportunity to go wrong, so we have to stick to -A because of this strange edgecase?

One approach that could make it safe would be to have the cop fail if multiple identical action names are detected.

@andyw8
Copy link
Contributor

andyw8 commented Sep 13, 2021

(normally Lint/DuplicateMethods would catch this, but that cop might be disabled).

@mollerhoj
Copy link
Contributor Author

Yeah. I could complicate things by trying to check for duplicates here, and disable auto correction in that case? Though it seems quite pedantic, and could lead to less clear code.

@andyw8
Copy link
Contributor

andyw8 commented Sep 14, 2021

I'd suggest aiming for a first release without safe-correction, and then safe-correction can be addressed in a follow-up.

@koic
Copy link
Member

koic commented Sep 14, 2021

aiming for a first release without safe-correction, and then safe-correction can be addressed in a follow-up.

Thank you for considering the corner case. However, whether it is an unsafe auto-correction is not determined by progress of implementation. This is determined by cop design.
https://docs.rubocop.org/rubocop/1.21/usage/auto_correct.html#safe-auto-correct

I think this cop can be safely designed due to changes to layout. So, if auto-correction is implemented, safe auto-correction (-a) should be the cop's implemented. If method names with the same name exist, the order must be guaranteed. e.g.

Before auto-correction

def edit
end

def index # first
end

def show
end

def index # second
end

After auto-correction

def index # first
end

def index # second
end

def show
end

def edit
end

Both should be remain for duplicate defined methods. So, I think it can make a design that compatible behavior. Can you add the above test case and for the implementation?

@mollerhoj
Copy link
Contributor Author

Both should be remain for duplicate defined methods. So, I think it can make a design that compatible behavior. Can you add the above test case and for the implementation?

It's done! And thanks, we avoided an infinite loop by testing this corner case (> changed to >=).

@mollerhoj
Copy link
Contributor Author

@pirj I feel like this one is good to go now?

Copy link
Member

@pirj pirj left a comment

Choose a reason for hiding this comment

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

Looks good overall 👍

I'd love to see a spec that shows how it behaves:

  • when non-resourceful methods are present in the controller
  • when private/protected methods are present

I personally don't mind turning this cop on by default (set it to pending now, and we'll flip it to enabled on a major release) - that's the reason the pending status was introduced, see https://docs.rubocop.org/rubocop/1.21/versioning.html#pending-cops
However, if you'd like to do so - please run the cop against real-world-rails to find out if there are any false positives or errors.
It's a good practice anyway to run newly introduced cops on a number of projects. We do this in rubocop-rspec at least.

lib/rubocop/cop/rails/action_order.rb Show resolved Hide resolved
@mollerhoj
Copy link
Contributor Author

mollerhoj commented Sep 14, 2021

I'd love to see a spec that shows how it behaves:

  • when non-resourceful methods are present in the controller

Do you mean spec/rubocop/cop/rails/action_order_spec.rb:70

  • when private/protected methods are present

I just looked into it. I guess we'll have to only run this cop on public methods. Unfortunately, I see no simple way of detecting if a method is public or not with rubocop? The only way of implementing this I can think of is to manually read through the class, detecting any access_modifiers (private or protected) and turn the cop off unless the public access_modifier if detected? I fear this will increase complexity dramatically.

@mollerhoj
Copy link
Contributor Author

I personally don't mind turning this cop on by default (set it to pending now, and we'll flip it to enabled on a major release) - that's the reason the pending status was introduced, see https://docs.rubocop.org/rubocop/1.21/versioning.html#pending-cops
However, if you'd like to do so - please run the cop against real-world-rails to find out if there are any false positives or errors.
It's a good practice anyway to run newly introduced cops on a number of projects. We do this in rubocop-rspec at least.

I'll look into it

@pirj
Copy link
Member

pirj commented Sep 14, 2021

we'll have to only run this cop on public methods

Makes sense.

no simple way of detecting if a method is public or not

There seems to be this and this, but frankly I never used any of them.

# 1.rb
class UserController < ApplicationController
  def commit; end
  def show; end
  private
  def index; end
end
# 2.rb
class UserController < ApplicationController
  def commit; end
  def show; end
  private def index; end
end
$ ruby-parse 1.rb
(class
  (const nil :UserController)
  (const nil :ApplicationController)
  (begin
    (def :commit
      (args) nil)
    (def :show
      (args) nil)
    (send nil :private)
    (def :index
      (args) nil)))
$ ruby-parse 2.rb
(class
  (const nil :UserController)
  (const nil :ApplicationController)
  (begin
    (def :commit
      (args) nil)
    (def :show
      (args) nil)
    (send nil :private
      (def :index
        (args) nil))))

For 2.rb it's possible to check if def isn't an argument to private, and for 1.rb skip everything below private (and protected). Hope those mixins would simplify the task.

@pirj
Copy link
Member

pirj commented Sep 14, 2021

when non-resourceful methods are present in the controller

Do you mean spec/rubocop/cop/rails/action_order_spec.rb:70

Please accept my apologies, missed that example completely 🙈

👍

@mollerhoj
Copy link
Contributor Author

mollerhoj commented Sep 16, 2021

This PR for merge is ready AFAIK.

@koic
Copy link
Member

koic commented Sep 16, 2021

This looks good to me. Can you use the new changelog entry format instead of CHANGELOG.md and squash your commits into one?
JFYI, the next release is scheduled for bug fix version 2.12.3. This PR is a new feature and will take some time to merge. Please wait for a while.

@koic
Copy link
Member

koic commented Oct 20, 2021

@mollerhoj ping :-)

@pirj
Copy link
Member

pirj commented Jan 11, 2022

@mollerhoj ping

@mollerhoj mollerhoj force-pushed the action-order-cop branch 3 times, most recently from a649a08 to f8cb390 Compare January 12, 2022 03:39
@mollerhoj
Copy link
Contributor Author

@koic @pirj thanks for the pings. This should be good now?

config/default.yml Outdated Show resolved Hide resolved
@koic koic merged commit 0ef065a into rubocop:master Oct 6, 2022
@koic
Copy link
Member

koic commented Oct 6, 2022

Thanks!

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.

Cop Idea: Controller Action Order
5 participants