-
Notifications
You must be signed in to change notification settings - Fork 26
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
Switch .count
to .size
where appropriate
#1605
Conversation
There's a But many controllers may call this partial, and hmmm.... where to add the |
app/classes/suggestion.rb
Outdated
@@ -68,7 +68,7 @@ def name_with_most_observations(names) | |||
best_name = nil | |||
best_count = -1 | |||
names.each do |name| | |||
count = name.observations.count | |||
count = name.observations.length |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if length
is right; I don't know whether this is right. (I don't how where it gets used in user workflow.)
Maybe use size
here and in other places? Is that bad form?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoeCohen I don't know either, but I can answer one part of it. According to internet, size
is an alias of length
. (on Medium)(on Ruby in Rails).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: Sorry, size
is NOT an alias of length
. Thank you Stack Overflow!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, that's an old answer. In the console, I notice that length
on an association that has already been fetched only counts the number of cached records, so that may have changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading through that whole thread, i think I should go with size
. Thanks for figuring that out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You made me look.
If we need the records, length
is better.
Else size
is better.
length(). Link
Returns the size of the collection calling size on the target. If the collection has been already loaded, length and size are equivalent. If not and you are going to need the records anyway this method will take one less query. Otherwise size is more efficient.
So it looks like size
is faster here. But I don't know if it's faster enough to be worth worrying about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From Roy Lindauer
count on a collection will always execute a COUNT() SQL statement to get an accurate count value. size returns the size of the collection, but will execute a COUNT() SQL statement if it's not already loaded. length returns the size of the collection from memory. If the collection has already been loaded and is in memory length and size are equivalent.
Relying on what's in memory may give you inaccurate results as the database could be modified while you are working on that collection. But making a bunch of expensive database calls to get an accurate count is probably something you want to avoid. There may be times when a count is preferred, but when in doubt it's probably better to use length.
also see diagrams here: https://www.akshaykhot.com/rails-length-size-count-difference/
I'm going to post all this stuff in a GitHub Discussion for reference.
@@ -100,7 +100,7 @@ def update_pref(pref, val) | |||
def update_content_filter(pref, val) | |||
filter = ContentFilter.find(pref) | |||
@user.content_filter[pref] = | |||
if filter.type == :boolean && filter.prefs_vals.count == 1 | |||
if filter.type == :boolean && filter.prefs_vals.length == 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though it's not the point of this PR, can you use
one?
instead of
length == 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I don't know that method. Will alter
@@ -112,7 +112,7 @@ def paginate_ids(paginator) | |||
ids = ids.select { |id| @letters[id] == letter } | |||
end | |||
end | |||
paginator.num_total = ids.count | |||
paginator.num_total = ids.length | |||
ids[paginator.from..paginator.to] || [] | |||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pellaea is this OK in Query::HighLevelQueries
? At the point of figuring out the paginator
and the @num_results
, the query is done, so it seems length
is more appropriate.
It may make no difference currently, but it will probably matter if Query starts using scopes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok i now think size
may be more appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh dear god! I can't possibly read that entire email thread right now!
I do want to make sure one thing is pointed out in this one case, though -- ids
here is not a query, it's just a plain old Array
. So there's no question of it executing SQL queries or anything if "done wrong".
(Is there in fact any difference between size, count and length on a plain old Array??... oh hold on, strike that question... it's almost certainly answered somewhere in the email thread I just deleted! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL
Switch to `size`
Switch to `one?`
@@ -350,7 +350,7 @@ def figure_out_where_to_go_back_to | |||
@back_object = Observation.safe_find(@back) | |||
return if @back_object | |||
|
|||
@back_object = if @collection_number.observations.count == 1 | |||
@back_object = if @collection_number.observations.length == 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another place for one?
, which is defined as
# File activerecord/lib/active_record/relation.rb, line 282
def one?
return super if block_given?
limit_value ? records.one? : size == 1
end
Note: I'm fine with not using one?
here and elsewhere. I'm just putting it out as an option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. Probably no on size
, stick with length
, as observations
is used on the next line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I went with one?
- If you get a chance please have another look over everything — i've changed everything in the PR — and check if it seems right.
switch to `one?`
Switch to `size`
Switch to `size`
Switch to `size`
Switch to `size`
Switch to `one?`
.count
to .length
where appropriate.count
to .size
where appropriate
Switch to `size`
Thank you. A nice, succinct explanation of the differences, plus a link to
a very useful flow chart.
…On Sun, Sep 10, 2023 at 7:23 PM andrew nimmo ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In app/classes/suggestion.rb
<#1605 (comment)>
:
> @@ -68,7 +68,7 @@ def name_with_most_observations(names)
best_name = nil
best_count = -1
names.each do |name|
- count = name.observations.count
+ count = name.observations.length
From Roy Lindauer
<https://www.roylindauer.com/blog/the-difference-between-length-size-and-count-in-ruby-on-rails.html>
count on a collection will always execute a COUNT(*) SQL statement to get
an accurate count value. size returns the size of the collection, but will
execute a COUNT(*) SQL statement if it's not already loaded. length
returns the size of the collection from memory. If the collection has
already been loaded and is in memory length and size are equivalent.
Relying on what's in memory may give you inaccurate results as the
database could be modified while you are working on that collection. But
making a bunch of expensive database calls to get an accurate count is
probably something you want to avoid. There may be times when a count is
preferred, but when in doubt it's probably better to use length.
also see diagrams here:
https://www.akshaykhot.com/rails-length-size-count-difference/
I'm going to post all this stuff in a GitHub Discussion for reference.
—
Reply to this email directly, view it on GitHub
<#1605 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAALDFHTHQZY7YY4ICBVHCTXZZYZVANCNFSM6AAAAAA4SND3XQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***
com>
|
I'm out of time and probably won't be able to return to this PR. |
Should resolve a number of mysterious n+1's.
Discussion in #1598, starting here
Please check the changes thoroughly, especially to classes and the model.