Handling MongoMapper EmbeddedDocument in Rails form
Asked Answered
H

2

3

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.

Hy answered 28/4, 2011 at 10:52 Comment(2)
I'm not sure if this helps, but the way this is typically accomplished is by declaring "accepts_nested_attributes_for" in the parent model (User in this case) and then the form submitting parameters that include "<thing>_attributes" (address_attributes in this case). I know that Mongoid supports accepts_nested_attributes_for. I don't think MongoMapper does. Some googling showed a few other folks asking for this feature, to no avail.Cymoid
Please see this question: #2480665Wensleydale
B
2

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.

Beach answered 28/4, 2012 at 22:16 Comment(0)
C
0

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.

Cornel answered 10/7, 2012 at 15:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.