Liviu Damian
Liviu Damian

Reputation: 63

Handling MongoMapper EmbeddedDocument in Rails form

First of all, I'm new to programming in general and new to Rails. I picked up Rails because it seems an easy language to start with. For my project I'm using MongoMapper with Rails.

I'm trying to process an Embedded Document in the same form as the Document.

I have the following model:

class User
  include MongoMapper::Document

  key :email, String, :required => true
  key :first_name, String
  key :last_name, String
  key :role, String
  many :addresses
  timestamps!
end

class Address
  include MongoMapper::EmbeddedDocument

  key :location, String
  key :street, String
  key :city, String
  key :zip, Integer
  key :state, String
  key :country, String

end

I want to create/edit the EmbeddedDocument at the same time as the Document. I have tried using fields_for:

<% f.fields_for :address, @user.addresses do |address| -%>
  <div class="field">
    <%= address.label :street %><br />
    <%= address.text_field :street %>
  </div>
<% end %>   

But I get

undefined method `street' for #<\Array:0x0000010126e3f8>

Thank you in advance.

Upvotes: 3

Views: 842

Answers (2)

ToreyHeinz
ToreyHeinz

Reputation: 595

As far as I remember fields_for does not include the id of the object, for that you will need to add a hidden field.

<%= address.hidden_field :id, :value => address.object.id %>

Then your addresses_attributes= method would look like this:

def addresses_attributes=(addresses_attributes)    
  addresses_attributes.each do |index, attrs|
    address = self.addresses.find(attrs['id']) || self.addresses.build
    address.attributes = attrs
  end
end

Thanks Brian, this provide a solution to a similar problem I was having.

Upvotes: 0

Brian Hempel
Brian Hempel

Reputation: 9094

fields_for will work if you define addresses_attributes= on User. For some reason fields_for actually changes its behavior if you define that method.

Here's an example implementation:

def addresses_attributes=(id_and_attrs)    
  id_and_attrs.each do |id, attrs|
    address = self.addresses.find(id) || self.addresses.build(:id => id)
    address.attributes = attrs
  end
end

Untested, so you'll have to work out the kinks. In particular, I don't remember how the nested parameters come through differently if the addresses are completely new because the user is new.

Upvotes: 2

Related Questions