Ensure #second (and others) acts like #first AR finder#13757
Conversation
|
Looking good to me! 👍 |
There was a problem hiding this comment.
This function should not have knowledge of :first, :second and friends. We should probably just pass the offset_value as argument.
|
@josevalim Ok, fixed that up for you! Any other concerns? |
There was a problem hiding this comment.
Added it after the examples! Thanks for the heads up!
|
@terracatta this looks good. Can you squash your commits? |
There was a problem hiding this comment.
I have a question: how problematic can this cached variable be now that we are using it for different "finds"?
There was a problem hiding this comment.
Very problematic. It will cache only the first call.
There was a problem hiding this comment.
Ok so I removed the caching here, but obviously that isn't the right way to go as that will cause multiple queries to fire unnecessarily when calling .first a bunch of times. I think the only option here is cache based on offset being passed into the private method.
Any other suggestions?
There was a problem hiding this comment.
ok I just went with that
|
@rafaelfranca @carlosantoniodasilva @senny, commits are squashed, updated the changelog, fixed the caching issue by dynamically setting and manually memoizing the instance variable based on the offset passed in. Tested it again on several personal rails projects and the test suite looks good! Any other feedback? |
There was a problem hiding this comment.
It is better to initialize a empty hash in the initialize of Relation and use the offset as the key to memoize it.
Since we are adding an internal variable to cache the value we have to update reset method
There was a problem hiding this comment.
Great suggestion, I'll implement it ASAP
|
@rafaelfranca, I made the requested changes, but couldn't reproduce your issue or create a failing test case (still trying), can you try again with the latest code and see if you still get a negative limit? |
This commit bring the famous ordinal Array instance methods defined in ActiveSupport into ActiveRecord as fully-fledged finders. These finders ensure a default ascending order of the table's primary key, and utilize the OFFSET SQL verb to locate the user's desired record. If an offset is defined in the query, calling #second adds to the offset to get the actual desired record. Fixes #13743.
|
@rafaelfranca Ok great, added better before examples for pg, sqlite3, and mysql2 gems. I also added some extra test cases for the offset functionality just in case! Anything else? Sorry for all the back and forth! |
|
Looks good. Thank you so much for working on this. |
Ensure #second (and others) acts like #first AR finder
|
Merged ❤️ |
There was a problem hiding this comment.
This is apparently not going to work with already loaded associations. Just testing around I got two different issues:
# consider the models `Author` has many `Post`s
## 1st scenario - raises exception
>> carlos.posts.reload.first
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."author_id" = ? [["author_id", 1]]
=> #<Post id: 1, author_id: 1, title: "ZOMG", body: nil, created_at: "2014-01-21 11:44:22", updated_at: "2014-01-21 11:44:22">
>> carlos.posts.reload.second
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."author_id" = ? [["author_id", 1]]
NoMethodError: undefined method 'first' for nil:NilClass
from....rails/rails/activerecord/lib/active_record/relation/finder_methods.rb:449:in 'find_nth'
## 2nd scenario - returns the same record
>> carlos.posts.first
=> #<Post id: 1, author_id: 1, title: "ZOMG", body: nil, created_at: "2014-01-21 11:44:22", updated_at: "2014-01-21 11:44:22">
>> carlos.posts.second
=> #<Post id: 1, author_id: 1, title: "ZOMG", body: nil, created_at: "2014-01-21 11:44:22", updated_at: "2014-01-21 11:44:22">
>> carlos.posts.third
=> #<Post id: 1, author_id: 1, title: "ZOMG", body: nil, created_at: "2014-01-21 11:44:22", updated_at: "2014-01-21 11:44:22">@terracatta can you take a look please? It'd be good to provide some tests for already loaded associations with some of these methods. Thanks.
There was a problem hiding this comment.
Absolutely! Thanks for testing!
This PR addresses issue #13743 where the ordinal ActiveSupport Array extentions were not assuming a default order like
firstwas.As suggested by @dhh this commit brings the famous ordinal Array instance methods defined
in ActiveSupport into ActiveRecord as fully-fledged finders.
These finders ensure a default ascending order of the table's primary key, and utilize the OFFSET SQL verb to locate the user's desired record. If an offset is defined in the query, calling #second adds
to the offset to get the actual desired record.
Example: