dynamoid icon indicating copy to clipboard operation
dynamoid copied to clipboard

MissingRangeKey when destroying associated objects

Open thomaswitt opened this issue 4 years ago • 4 comments

Let's say I've got two simple models:

class Company
  include Dynamoid::Document

  table name: :company,
        key: :name,
        capacity_mode: :on_demand
  range :metadata

  has_many :reports
end
class Report
  include Dynamoid::Document

  belongs_to :company

  field :content

end

Now I'll create a company (c = Company.create(name: 'test', metadata 'COMPANY#CA#LOSANGELES')) and create an association with it (r = c.report.create(content: 'this is my report')). Works fine.

Now I want to delete the report, which will lead to an error: p.destroy /Users/me/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/dynamoid-3.7.0/lib/dynamoid/finders.rb:165:in _find_by_id': Dynamoid::Errors::MissingRangeKey (Dynamoid::Errors::MissingRangeKey). Same error when I call c.report.first.destroy`.

What happens in DynamoDB, the report in the reports table will be deleted, but not from the company table. Why? I guess it has to do with having a combined range key in the Company table, so you can't locate the parent object. But how do I supply the range key to the destroy function?

thomaswitt avatar Apr 14 '21 13:04 thomaswitt

Yeah, you are right. Dynamoid doesn't support associations for tables with a compound primary key (that's with range key) right now. It isn't mentioned yet in the documentation - my bad.

Similar issue - https://github.com/Dynamoid/dynamoid/issues/472

andrykonchin avatar Apr 14 '21 17:04 andrykonchin

Wouldn't it be possible to allow to supply the range key query optionally in the Model of the associated table? My range key is a begins_with selector, so that'd be easy.

thomaswitt avatar Apr 15 '21 05:04 thomaswitt

It's an interesting idea but right now Dynanoid uses GetItem and BatchGetItem to load associated model/models (to delete them later) and it fails when the required range key is missing.

andrykonchin avatar Apr 15 '21 07:04 andrykonchin

Just FYI, my current workaround is:

class Report

  def destroy_recursive
    # See https://github.com/Dynamoid/dynamoid/issues/501
    c = Company.name(self.company_ids.first)
    c.company_ids.delete(self.id)
    c.save
    self.destroy rescue nil # Avoid the range key error
  end

end

Not pretty, but works.

thomaswitt avatar Apr 15 '21 08:04 thomaswitt