Cannot fetch_multi_by polymorphic field
I have made a new rails app with these models on the latest master of identity_cache:
models/item.rb
class Item < ApplicationRecord
include IdentityCache
belongs_to :widget, polymorphic: true
cache_belongs_to :widget
cache_index :widget
end
models/foo_widget.rb
class FooWidget < ApplicationRecord
include IdentityCache
has_many :items, as: :widget
cache_has_many :items, inverse: :widget
end
models/bar_widget.rb
class BarWidget < ApplicationRecord
include IdentityCache
has_many :items, as: :widget
cache_has_many :items, inverse: :widget
end
schema:
class AddTables < ActiveRecord::Migration[5.2]
def change
create_table :items do |t|
t.bigint :widget_id, null: false
t.string :widget_type, null: false
end
create_table :foo_widgets
create_table :bar_widgets
add_index :items, %i[widget_type widget_id]
end
end
I would like to be able to run this:
widgets = FooWidget.fetch_multi([1, 2, 3])
items = Item.fetch_multi_by_widget(widgets)
But, that generates an invalid SQL query:
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column: widget: SELECT widget, "items"."id" FROM "items" WHERE "items"."widget_type" = ? AND "items"."widget_id" IN (?, ?))
I can't change my cache_index to cache_index :widget_id, :widget_type because fetch_multi_by methods are only generated for cache_indexes with only one field.
I used to be able to pass in arrays into the fetch_by_widget_id_and_subject_type methods in 0.5.1, but now that doesn't work on master (e.g. an array of widget_ids generates a SQL query with NULL as the widget_id value). I guess was never the way those methods were intended to be used, but now I don't have a way to bulk fetch Items in a way that won't make N+1 queries when the cache is missed.
I can't change my cache_index to cache_index :widget_id, :widget_type because fetch_multi_by methods are only generated for cache_indexes with only one field.
Right, there isn't cache_attribute by multiple columns support, which means there is no cache_index by multiple columns support.
In your example
widgets = FooWidget.fetch_multi([1, 2, 3]) items = Item.fetch_multi_by_widget(widgets)
it looks like you could add cache_has_many :items, embed: :ids to FooWidget, then you could do
widgets = FooWidget.fetch_multi([1, 2, 3], include: :items)
items = widgets.flat_map(&:items)