1

I've been following a pretty standard UJS model for a lot of my AJAX and it works pretty well - however there's one situation where I'm not sure exactly what the best practice is. I have a model with a has_many relationship say:

class User < ActiveRecord::Base
  has_many :aliases
  accepts_nested_attributes_for :aliases, :allow_destroy => true
end

class Alias < ActiveRecord::Base
  belongs_to :User
end

Now, in my NEW view for a User object, I'd like the user to be able to click a button and add as many aliases as they like - each time they press the button it fires off a remote request to a controller action that looks like this:

def new_ajax
      @alias = Alias.new({})
      respond_to do |format|
        format.js
      end
  end

This replies with my new_ajax.js.erb template which looks like this:

$('#aliases-container').append('<%= j(render 'ajax_new')%>');

Which in turn renders a template which looks like this:

<%=simple_fields_for @alias do |f|%>
    <%= f.input :name %>
<% end %>

This all works and I get my Alias form field rendered - but the problem is the ID and the NAME attribute are not set correctly in the nested fields. The ID and the Alias should be numbered in sequence to provide for proper association building in the create method and for error handling. Does anyone have a solution to this problem?

user1813867
  • 1,045
  • 1
  • 9
  • 17

1 Answers1

1

The problem you have is the base problem with adding new nested fields.

The simple answer is to use child_index: Time.now.to_i for your fields_for; however, you've got to invoke it within a form_for object so that Rails creates the names etc correctly. Sounds complicated but it's quite simple when you get your head around it:


#app/controllers/users__controller.rb
class UsersController < ApplicationController
    respond_to :js, :html, only: :new
    def new
       @user = User.new
       @user.aliases.build if request.xhr?
       respond_with @user
    end
end

#app/views/users/new.html.erb
<%= render "form", locals: {user: @user} %>

#app/views/users/_form.html.erb
<%= form_for user do |f| %>
   <%= f.fields_for :aliases, child_index: Time.now.to_i do |a| %>
       <%= a.text_field :name %>
   <% end %>
<% end %>

#app/views/users/new.js.erb
var data = $("<%=j render "users/ajax_new", locals: {user: @user} %>").html();
$('#aliases-container').append(data);

You can see a more rudimentary implementation I wrote back in 2013: Rails accepts_nested_attributes_for with f.fields_for and AJAX

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147