I agree very much with James and would add that if iteration was done in this manner it would not improve performance since the additional queries add round-trip time (latency, db query setup, etc) which typically exceeds time spent returning results, especially in multi-tier environments. In my environment with 270k user rows, calling User.offset(x).first with five ID's varying by 50000 was 23% slower than calling User.all. I imagine this would be far worse for larger iteration strides.
As far as idiomatics are concerned, `all` returning an eagerly-loaded array is more idiomatic to me than `all` returning a proxy that quacks like an array but lazily-loads items. The current implementation of `all` makes working with a cohesive or related set of objects trivial, especially in the face of database contention. What happens if rows change while my application is making a bunch of queries for individual records? I would either risk getting inconsistent data or I'd have to create a locking scheme. These all seem like high prices to pay for a debatable idiomatic change. On Friday, July 19, 2013 7:40:27 AM UTC-4, James Coleman wrote: > > The whole point of the `all` method is that it actually fires the query on > the current relation. So 1.) a change like this could potentially break a > lot of existing code and 2.) it would defeat the point of the method. So I > strongly believe that it shouldn't change. If you want the limit/offset > query, use those methods. That's why they're there. > > > On Fri, Jul 19, 2013 at 12:14 AM, Michael Swan <[email protected]<javascript:> > > wrote: > >> Your example would involve three queries, each only allocating memory and >> transferring content from the DBMS for 1 result, instead of every record in >> the table. >> >> In the present: >> User.all[5] # SELECT "users".* FROM "users" -> 420,000 results >> >> My suggestion: >> User.all[5] # SELECT "users".* FROM "users" LIMIT 1 OFFSET 5 -> 1 result >> >> If I understand right, every User is pulled from the database, an array >> is created with every single possible instance of a User, and then you >> select a specific value from that array. I am thinking about this in the >> context of any query. If you want the nth result from that query, it would >> be nice to have an idiomatic shorthand for that, instead of >> ".offset(n).first". >> >> It appears that even if you are iterating over the elements in a query in >> such a way, my suggestion would improve performance. This has nothing to do >> with any of the other functions that are delegated to Array. This is for an >> ActiveRecord query that one is looking for the nth element within those >> query results. >> >> No one in their right mind would use the delegated '[]' function on a >> query that could have thousands of results. But they would call the '[]' >> function that I am suggesting. >> >> On Friday, July 12, 2013 1:28:18 PM UTC-4, Olly Smith wrote: >>> >>> What do you expect to happen if the code looks like this: >>> >>> User.all[5] >>> User.all[6] >>> User.all[7] >>> >>> Should ActiveRecord make three separate queries? How about if the code >>> iterates from index 100 to 200? >>> >>> Imho, it's totally acceptable to sacrifice 'idiomatic' ruby in this case >>> in favour of fewer accidental gotchas. >>> >>> Olly >>> On 12 Jul 2013 17:29, "Michael Swan" <[email protected]> wrote: >>> >>>> I am going to make this quick. Try something like: User.all[5] >>>> Rails presently runs the following query in Postgres: SELECT "users".* >>>> FROM "users" >>>> And then gets the 6th element from the array of results. >>>> >>>> In reality, User.all[5] should be equivalent to: >>>> User.limit(1).offset(5).first >>>> in all circumstances that this addition to the query can be performed. >>>> This means that someone looking for the nth User, for example, can >>>> simply use the brackets as is idiomatic in Ruby, to perform the query >>>> which >>>> is truly desired by the user. >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Ruby on Rails: Core" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to rubyonrails-co...@**googlegroups.com. >>>> To post to this group, send email to rubyonra...@googlegroups.**com. >>>> Visit this group at >>>> http://groups.google.com/**group/rubyonrails-core<http://groups.google.com/group/rubyonrails-core> >>>> . >>>> For more options, visit >>>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out> >>>> . >>>> >>>> >>>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Ruby on Rails: Core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> To post to this group, send email to >> [email protected]<javascript:> >> . >> Visit this group at http://groups.google.com/group/rubyonrails-core. >> For more options, visit https://groups.google.com/groups/opt_out. >> >> >> > > -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/rubyonrails-core. For more options, visit https://groups.google.com/groups/opt_out.
