Open roccoblues opened 6 years ago
This is working as intended.
irb(main):002:0> client.fetch_persons.map{|p| p.client.object_id}
You need to replace the Person#client
call with Person#fetch_client
if you want the cached record. Try this instead
irb(main):002:0> client.fetch_persons.map{|p| p.fetch_client.object_id}
That fetches the client from cache for every person and results in different client objects:
irb(main):002:0> client.fetch_persons.map{|p| p.fetch_client.object_id}
(0.7ms) SELECT `persons`.`id` FROM `persons` WHERE `persons`.`deleted_at` IS NULL AND `persons`.`client_id` = 4 AND `persons`.`partner_id` IS NULL
Cache cas_multi: greenlight:1:IDC:7:blob:Person:14507715566204489110:9/IDC:7:blob:Person:14507715566204489110:10/IDC:7:blob:Person:14507715566204489110:11/IDC:7:blob:Person:14507715566204489110:3459/IDC:7:blob:Person:1450771556620:md5:86dc7956880e3af3985af73a2db3aec2 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:9 (multi)
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:10 (multi)
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:11 (multi)
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:3459 (multi)
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:4135 (multi)
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:4147 (multi)
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:4312 (multi)
[IdentityCache] (backend) cache hit for IDC:7:blob:Person:14507715566204489110:4458 (multi)
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
Cache cas: greenlight:1:IDC:7:blob:Client:2431980387103363215:4 ({:namespace=>"greenlight:1", :expires_in=>21600})
[IdentityCache] (cache_backend) cache hit for IDC:7:blob:Client:2431980387103363215:4
=> [70107689539100, 70107689572200, 70107689434820, 70107689369160, 70107692043900, 70107689250420, 70107689202020, 70107666820400]
My problem is that I have some expensive associations already fetched in the client that I would like to reuse on person.client.[expensive_stuff]
calls. That's why I want to have all person.client
objects to be the same as the one we fetched the persons on.
I guess I can set that up myself with something like this:
irb(main):003:0> client.fetch_persons.map{|p| p.client = client; p}.map{|p| p.client.object_id}
=> [70107688039420, 70107688039420, 70107688039420, 70107688039420, 70107688039420, 70107688039420, 70107688039420, 70107688039420]
But I'm still wondering if it isn't something that IdentityCache could do. If you're open for it I could try to create a pull-request.
Thanks!
Oh I see. It looks like cache_hasmany with embed: :ids
implements the `fetch#{association}` method by just memoizing a fetch_multi on the associated class.
Yes, it would make sense if the inverse cached association were set on the returned records.
By the way, I think that works for cache_has_many associations with the embed: true
option.
I've started by adding tests for the inverse_of
behaviour here: https://github.com/roccoblues/identity_cache/commit/01219cce14289431c57697a541c6bc4fa271b6e4
Do you agree that the two failing ones should be fixed?
1) Failure:
PrefetchAssociationsTest#test_fetch_should_setup_association_for_cache_has_many [test/inverse_of_test.rb:38]:
Expected: 70228404239540
Actual: 70228404877000
2) Failure:
PrefetchAssociationsTest#test_fetch_should_setup_association_for_cache_has_many_embedded_ids [test/inverse_of_test.rb:60]:
Expected: 70228399614120
Actual: 70228392031260
Yes, although you don't need both of those tests, since the only difference is that one tests the default value of the cache_has_many embed
keyword argument.
Not sure if it's a misconfiguration on my side or if it's simply not supported.
Rails 5.1.4 identity_cache 0.5.1
Given:
Without the cache the client isn't fetched again when we fetch persons on a client:
With IdentityCache I get a client query for every person and different objects. Shouldn't IdentityCache simply setup the association to the existing client object?