Skip to content

Commit

Permalink
Allowing filtering on the primary model when a dependency has changed (
Browse files Browse the repository at this point in the history
  • Loading branch information
praveenram committed Sep 27, 2021
1 parent 38b008e commit 5e58c70
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 6 deletions.
8 changes: 7 additions & 1 deletion lib/thermos/beverage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ def lookup_keys_for_dep_model(dep_model)
@deps.select do |dep|
dep.klass == dep_model.class
end.flat_map do |dep|
lookup_keys = []

@model.joins(dep.path)
.where(dep.table => { id: dep_model.id })
.pluck(@lookup_key)
.find_each do |model|
lookup_keys << model.send(@lookup_key) if should_fill?(model)
end

lookup_keys
end.uniq
end

Expand Down
6 changes: 2 additions & 4 deletions lib/thermos/refill_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ def refill_primary_caches(model)

def refill_dependency_caches(model)
BeverageStorage.instance.beverages.each do |beverage|
if beverage.should_fill?(model)
beverage.lookup_keys_for_dep_model(model).each do |lookup_key|
Thermos::RebuildCacheJob.perform_later(beverage.key, lookup_key)
end
beverage.lookup_keys_for_dep_model(model).each do |lookup_key|
Thermos::RebuildCacheJob.perform_later(beverage.key, lookup_key)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/thermos/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Thermos
VERSION = '0.5.1'
VERSION = '0.5.2'
end
4 changes: 4 additions & 0 deletions test/dummy/app/models/category.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ class Category < ActiveRecord::Base
has_many :products, through: :category_items
belongs_to :store

def ball?
name.match("ball")
end

def as_json(*args)
{
name: name,
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/stores.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
sports:
name: sports store
supermarket:
name: supermarket store
83 changes: 83 additions & 0 deletions test/thermos_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,28 @@ def teardown
assert_raises(MockExpectationError) { mock.verify }
end

test "allows filtering based on the beverage when multiple beverages are configured and only one of them has a filter" do
mock = Minitest::Mock.new
store = stores(:supermarket)
category = categories(:baseball)
# filter method specific to one model
# store.ball? doesn't exist
filter = ->(model) { model.ball? }

Thermos.fill(key: "key", model: Category, lookup_key: "name", filter: filter) do |name|
mock.call(name)
end

Thermos.fill(key: "key_2", model: Store, lookup_key: "name") do |name|
mock.call(name)
end

mock.expect(:call, 1, ["groceries"])
store.update!(name: "groceries")
assert_equal 1, Thermos.drink(key: "key_2", id: "groceries")
mock.verify
end

# has_many model changes
test "rebuilds the cache on has_many model change" do
mock = Minitest::Mock.new
Expand Down Expand Up @@ -223,6 +245,26 @@ def teardown
assert_raises(MockExpectationError) { mock.verify }
end

test "re-builds the cache for has_many record changes when filter condition is met" do
mock = Minitest::Mock.new
category = categories(:baseball)
filter = ->(model) { model.ball? }

Thermos.fill(key: "key", model: Category, deps: [:category_items], filter: filter) do |id|
mock.call(id)
end

mock.expect(:call, 1, [category.id])
CategoryItem.create!(category: category)
mock.verify

category.update!(name: "hockey")

mock.expect(:call, 1, [category.id])
CategoryItem.create!(category: category)
assert_raises(MockExpectationError) { mock.verify }
end

# belongs_to model changes
test "rebuilds the cache on belongs_to model change" do
mock = Minitest::Mock.new
Expand Down Expand Up @@ -286,6 +328,27 @@ def teardown
assert_raises(MockExpectationError) { mock.verify }
end

test "re-builds the cache for belongs_to record changes when filter condition is met" do
mock = Minitest::Mock.new
category = categories(:baseball)
filter = ->(model) { model.ball? }

Thermos.fill(key: "key", model: Category, deps: [:store], filter: filter) do |id|
mock.call(id)
end

mock.expect(:call, 1, [category.id])
mock.expect(:call, 1, [category.id])
Store.create!(name: "foo", categories: [category])
mock.verify

category.update!(name: "hockey")

mock.expect(:call, 2, [category.id])
Store.create!(name: "bar", categories: [category])
assert_raises(MockExpectationError) { mock.verify }
end

# has_many through model changes
test "rebuilds the cache on has_many through model change" do
mock = Minitest::Mock.new
Expand Down Expand Up @@ -348,6 +411,26 @@ def teardown
assert_raises(MockExpectationError) { mock.verify }
end

test "re-builds the cache for has_many through record changes when filter condition is met" do
mock = Minitest::Mock.new
category = categories(:baseball)
filter = ->(model) { model.ball? }

Thermos.fill(key: "key", model: Category, deps: [:products], filter: filter) do |id|
mock.call(id)
end

mock.expect(:call, 1, [category.id])
Product.create!(categories: [category])
mock.verify

category.update!(name: "hockey")

mock.expect(:call, 2, [category.id])
Product.create!(categories: [category])
assert_raises(MockExpectationError) { mock.verify }
end

test "handles indirect associations" do
mock = Minitest::Mock.new
category = categories(:baseball)
Expand Down

0 comments on commit 5e58c70

Please sign in to comment.