4 ms·
The thing that most annoyed me about Rails (not Ruby) was that users.size users.length users.count are all valid, all useful, all have different m
by strken 6y ago
The thing that most annoyed me about Rails (not Ruby) was that
users.size
users.length
users.count
are all valid, all useful, all have different meanings, are all present in plain Ruby but with different meanings, and contain absolutely no information about what they do.
For reference, .length loads everything and gets the length of the collection, .count runs a SQL COUNT query, and .size uses length if the query has already been run and .count if it hasn't.
- nsomaru 6y agoSo why would you not just default to always using .size?
- pawelduda 6y agoThere are no guarantees that the count will remain correct after the first run of the query.
- adrusi 6y agoYou usually want to know when you're hitting the database. "Hit the database if the value isn't cached" is useful behavior, but should probably be telegraphed a bit more precisely than just the word "size".
- mosselman 6y ago“size” is fine. The person you are responding to is trying to say that complaining about multiple options is a bit strange as you can just use one option. Why is it an issue that other options exist? Who cares. There are synonyms for English words as well, is that an issue as well?
- tinus_hn 6y agoThey are not synonyms, they mean slightly different things. And that is the problem. Because for small datasets the difference doesn’t matter this results in beginner programmers choosing randomly, which 2/3 of time is the wrong choice.
- mosselman 6y agoSo if 'length' was the only option and I'd have to do ActiveRecord::Base.connection.execute('SELECT count(*) FROM users').values.first or something it would all be fine?
- strken 6y agoOther ORMs separate building the query from executing the query, which is less ergonomic but more explicit. Drawing on Rust, https://diesel.rs/ https://diesel.rs/ shows how this approach would work: users.select(count_star()).first(&connection) which is really just a cleaned-up version of your suggestion. Of course, you could imagine an ActiveRecord-like API to make this nicer: User.first{|t| t.count} User.first{|t| t.count}.execute! User.execute{|t| t.count}.values.first # ...etc. but the underlying problem is that building the query and executing the query are two discrete steps, Rails streamlines them instead of making the separation obvious, and when a system hides complexity it becomes harder to know what it's really doing.
- adrusi 6y ago"size" is not fine. If I'm conditionally hitting the database, I want that to be as explicit as possible.
- joelbluminator 6y agoUgh yes I don't like this as well. Even if they're all useful, I'd do it with one method that accepts some optional arguments, this is unnecessarily confusing.
- majormajor 6y agoI learned Ruby by itself and only worked on Rails code later... so I've had a lot fewer core Ruby complaints then most. But Rails has definitely become a PR problem for the language in terms of how many complaints like this it leads to.