2

I want to be able to replace the entire set of embedded documents in a MongoDB object on save - the HTML form will contain the entire new set.

I also want it to validate everything before saving - i.e. don't trash the old documents, then validate each one as it gets added.

I've come up with an implementation, but it's not persisting - none of the new embedded documents show up. An added complication is that there is inheritance involved. Here's (simplified) the set of models I have so far:

class Person
  include Mongoid::Document
  embeds_many :vehicles
end

class Vehicle 
  include Mongoid::Document
  embedded_in :person
end

class Car < Vehicle
end

class Motorbike < Vehicle
end

In order to work out what kind of vehicle to instantiate when the user submits the form, I've added this method to the Person class:

def build_from_hash(hash)
   @vehicles= []
   hash.each do |idx, vehicle|
      if vehicle[:_type].constantize < Inclusion # Check for inheritance, for security
         self.vehicles.push vehicle[:_type].constantize.new(vehicle)
      end
   end
end

And modified the controller to call it:

def submit_build
  @person= current_user.persons.find(params[:id])
  @person.build_from_hash(params[:vehicles]) if params.has_key? :vehicles

  respond_to do |format|
    if @person.save # Also tried: @person.update_attributes(inclusions: @person.vehicles)
      format.html { redirect_to @person, notice: 'Person was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: "build" }
      format.json { render json: @person.errors, status: :unprocessable_entity }
    end
  end
end

No errors generated - the page redirects as if it had worked, but when I examine it again there are no embdedded documents.

Using Rails 3.2.8, Mongoid 3.0.5, MongoDB 1.8.3.

p.g.l.hall
  • 1,961
  • 2
  • 15
  • 26

1 Answers1

0

I figured out how to do this in a more standard Rails-esque way, albeit with a workaround for some peculiar behaviour.

Short answer: the Person class needed to accepts_nested_attributes_for :vehicles and I had to remove all the custom stuff from the controller, replacing the action with a standard update action. But it wouldn't accept the _type parameter for the subclasses of Vehicle unless the Rails process had already instantiated an object of each of those subclasses, so I was forced to work around it with an initialiser like this:

Car.new
Motorbike.new

Long answer is on the Mongoid Google group.

p.g.l.hall
  • 1,961
  • 2
  • 15
  • 26