-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
"Redundant all
" is too naive
#347
Comments
cc @masato-bkn |
Hey Victor! Interesting case with delete_all indeed. But how is the styleguide/cop responsible for such an inconsistent and surprising behavior in Rails? I wouldn’t be surprised if it was a many to many association, like ‘peter.friends.delete_all’. But it would remove records from the join table, not nullify, wouldn’t it? I’d stick to “no .all unless it’s directly called on the model” and let Rails reconsider its default that goes against the principle of least surprise. Wondering what actions would you guys take to make everyone’s lifes easier? |
The example ‘person.pets.delete(Pet.find(1))’ looks quite weird. I would probably write it differently, but this notation deserves to exist. In contrast to the surprising nullify for delete_all on has_many, this is a real dilemma. Pets can become orphans, and another person can adopt it. But an article, a doctor appointment, a diary note? To this moment I was trying to avoid ‘dependent:’ as much as possible, and to rely on DB consteaints instead (‘add_foreign_key … on_delete: :cascade’. However, your example shows that onitting ‘dependent:’ isn’t always a good idea. Do you think it makes sense to require to specify ‘dependent:’ on every has_many/has_many through? |
My only point was that suggesting (in the style guide and cop rule) that So, at the very least:
PS: On a more philosophical note, there could be a lot of discussion around CollectionProxy design (which sometimes has the same behavior as a naked scope, and sometimes has completely different with same method names, and it all "makes sense in context" until you work in a big production codebase or follow the wrong assumption), but that's just the reality we have 🤷 |
It’s a very good point. I doubt that the guide is providing guarantees that switching from a “bad” style to a “good” style is always safe and has no side effects. Take, for example, the load Rails config defaults rule. Blindly turning the loading on can have disastrous effects, not all of which can be caught by specs or on a low-load few-data staging server. Speaking if the cop, it should be marked as unsafe for autocorrection. |
A practical clarification. Why wasn’t the change from ‘user.articles.all.delete_all’ to ‘user.articles.delete_all’ detected? I recon it should have been caught by a not null database constraint on ‘articles.user_id’ column? |
That's true. But I believe that at least mentioning the fact about possible change of the semantics should be considered 🤷
It was caught by the test immediately, but I spent some time trying to understand why |
Thank you for pointing that out. Considering that the behavior of some methods changes when the receiver is a associations, it might be better to limit this style guide and cop to situations where the receiver is a Model🤔 When the receiver is a Model, at least for methods in |
The guideline can make a note regarding the ‘delete’/‘delete_all’ and the default ‘dependent’. Do you think this would promote the style that has the least surprise? |
OK, I generally agree with you!
At present, this cop checks for Also, for |
I am not sure whether it should be reported as style guide problem, or rubocop-rails problem, but it is a problem :)
Basically, the styleguide claims and the cop supports this claim, that those statements are equivalent:
The latter is incorrect at least in a case of
delete_all
(which I shoot myself in a foot with just recently, after update to the latest rubocop-rails):user.articles.all.delete_all
is ActiveRecord::Relation#delete_all which will just do SQL DELETE, done and forgotten;user.articles.delete_all
is ActiveRecord::Associations::CollectionProxy#delete_all which behaves "according to a deletion strategy", which, say, forhas_many
is by default:nullify
.E.g.:
user.articles.all.delete_all
=DELETE FROM articles WHERE user_id=1
(delete articles in this scope)user.articles.delete_all
=UPDATE articles WHERE user_id=1 SET user_id=NULL
(remove articles of this scope from the collection "articles of this user")Which is... Quite a difference. I love Rails and its conventions 😍
So... Probably both the style guide and the cop should be much more cautious here.
The text was updated successfully, but these errors were encountered: