Shopify / Shopify/identity_cache

IdentityCache in combination with module causes "undefined method `all'"

Open
#298 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
2k
Forks
174
Avg merge
13m
Merged PRs (30d)
3

Description

Hi,

Thanks for developing this, it's neat (when it works ;)).

Recently I encountered a rather peculiar bug that I eventually traced down to IdentityCache.
At one point my code looked like this:

class Card < Identifiable
  cache_index :card, unique: :true

  belongs_to :employee, inverse_of: :cards
  cache_belongs_to :employee
  validates_associated :employee
  validates :employee, presence: true
end

class PlateOwner < ApplicationRecord
  self.abstract_class = true
  include IdentityCache
  acts_as_paranoid
end

class Numberplate < Identifiable
  cache_index :plate, unique: :true

  belongs_to :plate_owner, -> { with_deleted }, polymorphic: true, inverse_of: :numberplates
  cache_belongs_to :plate_owner
  validates_associated :plate_owner
  validates :plate_owner, presence: true
end

I then refactored it to use concerns rather than using inheritance for identifiable. After the refactor, my code looked like this:

class Card < ApplicationRecord
  include Identifiable
  cache_index :card, unique: :true

  belongs_to :employee, inverse_of: :cards
  cache_belongs_to :employee
  validates_associated :employee
  validates :employee, presence: true
end

module Identifiable
  extend ActiveSupport::Concern

  included do
    include IdentityCache
    acts_as_paranoid

    has_many :events, as: :identifiable, inverse_of: :identifiable
    cache_has_many :events, embed: true
  end

  module ClassMethods
  end
end

class Numberplate < ApplicationRecord
  include Identifiable

  cache_index :plate, unique: :true

  belongs_to :plate_owner, -> { with_deleted }, polymorphic: true, inverse_of: :numberplates
  cache_belongs_to :plate_owner
  validates_associated :plate_owner
  validates :plate_owner, presence: true
end

Then things went south. I started to get very weird errors like undefined method all' for Identifiable:Module` when saving a new Card for instance.
Here's a stack trace:

app/controllers/cards_controller.rb:34:in `block in create'
app/controllers/cards_controller.rb:33:in `create'
app/controllers/application_controller.rb:22:in `block in identity_cache_memoization'
app/controllers/application_controller.rb:22:in `identity_cache_memoization'

It took quite some time to pinpoint the issue being caused by IdentityCache in combination with the new module. I'm not sure what's actually causing it, but no longer including identity cache in my code solves the problem for me.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the reported Card and Numberplate setup using the IdentityCache and Identifiable examples, then follow the failure from app/controllers/cards_controller.rb and app/controllers/application_controller.rb. Inspect the interaction between the included module and IdentityCache while saving a new Card; done means the save no longer raises undefined method `all' for Identifiable:Module and the regression is covered by a test.

Written by the indexing model from the issue text.

Assessment

Tech stack
rails, ruby
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.