Cjoerg
Cjoerg

Reputation: 1325

Destroy an embedded Mongoid document by specifying its "id" (instead of finding it through its parent)

I have these two models:

class Presentation
  include Mongoid::Document
  embeds_many :presentation_rows
end

class PresentationRow
  include Mongoid::Document
  embedded_in :presentation
end

In my presentation_rows_controller.rb I have these lines of code:

def show
  @presentation = Presentation.find(params[:id])
  @presentation_rows = @presentation.presentation_rows
end

def destroy
  ...
  ...
end

In my presentation_rows/show.html.haml I have these lines of code:

- @presentation_rows.each do |presentation_row|
  = link_to "Delete", presentation_row, method: :delete

I have tried many approaches in the destroy controller action, but they all point back to the obvious fact that I am trying to destroy an embedded document without going through its parent. But now that I in my view file have the presentation_row by its id it seems silly that I should not be allowed to destroy it.

Error message with an empty destroy action, fyi:

Started DELETE "/en/presentation_rows/516af0a983c336708300000f" for 127.0.0.1 at 2013-04-14 20:08:47 +0200
Processing by PresentationRowsController#destroy as HTML
  Parameters: {"authenticity_token"=>"KHGG2dsTseCl88okOKW9JAlHb+VaK2lKIxb0ptAIC7A=", "locale"=>"en", "id"=>"516af0a983c336708300000f"}
  MOPED: 127.0.0.1:27017 QUERY        database=shop_import_development collection=users selector={"$query"=>{"_id"=>"511a813a83c336a0ea000001"}, "$orderby"=>{:_id=>1}} flags=[:slave_ok] limit=-1 skip=0 fields=nil (0.3152ms)
  MOPED: 127.0.0.1:27017 QUERY        database=shop_import_development collection=presentations selector={"_id"=>"516af0a983c336708300000f"} flags=[:slave_ok] limit=0 skip=0 fields=nil (0.2129ms)
Completed 500 Internal Server Error in 2ms

Mongoid::Errors::DocumentNotFound (
Problem:
  Document(s) not found for class Presentation with id(s) 516af0a983c336708300000f.
Summary:
  When calling Presentation.find with an id or array of ids, each parameter must match a document in the database or this error will be raised. The search was for the id(s): 516af0a983c336708300000f ... (1 total) and the following ids were not found: 516af0a983c336708300000f.
Resolution:
  Search for an id that is in the database or set the Mongoid.raise_not_found_error configuration option to false, which will cause a nil to be returned instead of raising this error when searching for a single id, or only the matched documents when searching for multiples.):
  app/controllers/presentation_rows_controller.rb:16:in `correct_user?'


  Rendered /Users/christoffer/.rvm/gems/ruby-1.9.3-p385/gems/actionpack-3.2.8/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.0ms)
  Rendered /Users/christoffer/.rvm/gems/ruby-1.9.3-p385/gems/actionpack-3.2.8/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.8ms)
  Rendered /Users/christoffer/.rvm/gems/ruby-1.9.3-p385/gems/actionpack-3.2.8/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (9.2ms

What should I put into the destroy action?

Upvotes: 2

Views: 1757

Answers (1)

Leopd
Leopd

Reputation: 42717

This is a limitation of mongoid. Quoth a contributor "Embedded documents must always be accessed through the parent." https://github.com/mongoid/mongoid/issues/348

Note that this is not a limitation of mongodb. The workaround to get the PresentationRow object from its id is...

pres = Presentation.where('presentation_rows._id' => Moped::BSON::ObjectId(params[:id])).first
row = pres.presentation_rows.detect { |pr| pr.id.to_s == params[:id] }
row.destroy

Add an index to presentation_rows._id if you have a lot of them.

Upvotes: 7

Related Questions