How do i delete an embedded document in mongomapper?
-
20-09-2019 - |
Question
Hi Guys I run a sinatra application with mongomapper. I have models called Movie(Document) and Cover(EmbeddedDocument).I embed covers into movies using
@movie.covers << @cover
@movie.save
This works great. when hit @movies.covers I got the array of embedded documents. But I am not able to destroy the embedded document. I tried something like this
@movie.covers.each do |c|
c.destroy
end
NoMethodError: undefined method `destroy' for #<Cover:0xb7b20734>
from (irb):5
from /usr/lib/ruby/gems/1.8/gems/mongo_mapper-0.6.8/lib/mongo_mapper/associations/proxy.rb:85:in `call'
from /usr/lib/ruby/gems/1.8/gems/mongo_mapper-0.6.8/lib/mongo_mapper/associations/proxy.rb:85:in `method_missing'
from /usr/lib/ruby/gems/1.8/gems/mongo_mapper-0.6.8/lib/mongo_mapper/associations/proxy.rb:85:in `each'
from /usr/lib/ruby/gems/1.8/gems/mongo_mapper-0.6.8/lib/mongo_mapper/associations/proxy.rb:85:in `send'
from /usr/lib/ruby/gems/1.8/gems/mongo_mapper-0.6.8/lib/mongo_mapper/associations/proxy.rb:85:in `method_missing'
from (irb):4
from :0
Can anyone temme how to destroy it? It would be great if someone enlightens me how to update the embedded document.
Solution
Covers are stored as an array within movie object, therefore you can do e.g.:
@movie.covers.clear
@movie.save
or if you want to be selective
@movie.covers.delete_if {|cover| cover.name == "bla"}
@movie.save
OTHER TIPS
This works if your deleting based on an attribute like a name, but if you already know the id and want to delete it, use this trick from p-rob's tubmlr post:
def destroy
@phone_number = @person.phone_numbers.find(params[:id])
@person.phone_numbers.delete_if{|phone_number| phone_number.id == @phone_number.id}
if @person.save
redirect_to @person
else
flash[:error] = "dag, yo."
end
end
I really struggled with this :(
here is a quick and dirty complete gist for deleting an embedded document from an association. Repeated here:
class Period
include MongoMapper::EmbeddedDocument
key :text, String
embedded_in :schedule
def to_s
text
end
end
class Schedule
include MongoMapper::Document
key :name, String
many :periods
def to_s
text = "#{name}, periods: " + periods.join(', ')
end
end
s1 = Schedule.create(:name => "Thursday",
:periods => [
Period.new(:text => "Morning"),
Period.new(:text => "Afternoon"),
Period.new(:text => "Evening")
])
puts s1
#Thursday, periods: Morning, Afternoon, Evening
s1.periods.delete_if{|p| p.text == 'Afternoon'}
s1.save
puts s1
# Thursday, periods: Morning, Evening