Rails: ¿Cómo administrar los atributos anidados sin utilizar accept_nested_attributes_for?

Mi problema es que me he topado con las limitaciones de accept_nested_attributes_for, así que necesito descubrir cómo replicar esa funcionalidad por mi cuenta para tener más flexibilidad. (Vea a continuación exactamente lo que me está colgando.)Entonces, mi pregunta es: ¿Cómo deberían ser mi formulario, mi controlador y mis modelos si quiero imitar y aumentar aceptados los atributos_valorados? El verdadero truco es que necesito poder actualizar tanto los modelos existentes Y nuevos con las asociaciones / atributos existentes.

Estoy construyendo una aplicación que utiliza formularios anidados. Inicialmente utilicé este RailsCast como modelo (aprovechando accept_nested_attributes_for):Railscast 196: Forma de modelo anidado.

Mi aplicación es listas de verificación con trabajos (tareas), y estoy permitiendo que el usuario actualice la lista de verificación (nombre, descripción) y agregue / elimine trabajos asociados en un solo formulario. Esto funciona bien, pero tengo problemas cuando lo incorporo a otro aspecto de mi aplicación: el historial a través del control de versiones.

Una gran parte de mi aplicación es que necesito registrar información histórica para mis modelos y asociaciones. Terminé rodando mi propia versión (aquí es mi pregunta donde describo mi proceso de decisión / consideraciones), y una gran parte de eso es un flujo de trabajo donde necesito crear una nueva versión de algo antiguo, hacer actualizaciones a la nueva versión, archivar la versión antigua. Esto es invisible para el usuario, quien ve la experiencia como simplemente actualizar un modelo a través de la interfaz de usuario.

Código - modelos

#checklist.rb
class Checklist < ActiveRecord::Base
  has_many :jobs, :through => :checklists_jobs
  accepts_nested_attributes_for :jobs, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end

#job.rb
class Job < ActiveRecord::Base
  has_many :checklists, :through => :checklists_jobs
end

Código: formulario actual (NOTA: @jobs se define como trabajos no archivados para esta lista de verificación en la acción de edición del controlador de listas de verificación; también lo es @checklist)

<%= simple_form_for @checklist, :html => { :class => 'form-inline' } do |f| %>
  <fieldset>
    <legend><%= controller.action_name.capitalize %> Checklist</legend><br>

    <%= f.input :name, :input_html => { :rows => 1 }, :placeholder => 'Name the Checklist...', :class => 'autoresizer'  %>
    <%= f.input :description, :input_html => { :rows => 3 }, :placeholder => 'Optional description...', :class => 'autoresizer' %>

    <legend>Jobs on this Checklist - [Name] [Description]</legend>

    <%= f.fields_for :jobs, @jobs, :html => { :class => 'form-inline' } do |j| %>
        <%= render "job_fields_disabled", :j => j %>
    <% end %>
    </br>
    <p><%= link_to_add_fields "+", f, :jobs %></p>

    <div class="form-actions">
      <%= f.submit nil, :class => 'btn btn-primary' %>
      <%= link_to 'Cancel', checklists_path, :class => 'btn' %>
    </div>
  </fieldset>
<% end %>

Código: fragmento de checklists_controller.rb # Actualizar

def update
  @oldChecklist = Checklist.find(params[:id])

# Do some checks to determine if we need to do the new copy/archive stuff
  @newChecklist = @oldChecklist.dup
  @newChecklist.parent_id = (@oldChecklist.parent_id == 0) ? @oldChecklist.id : @oldChecklist.parent_id
  @newChecklist.predecessor_id = @oldChecklist.id
  @newChecklist.version = (@oldChecklist.version + 1)
  @newChecklist.save

# Now I've got a new checklist that looks like the old one (with some updated versioning info).

# For the jobs associated with the old checklist, do some similar archiving and creating new versions IN THE JOIN TABLE
  @oldChecklist.checklists_jobs.archived_state(:false).each do |u|
    x = u.dup
    x.checklist_id = @newChecklist.id
    x.save
    u.archive
    u.save
  end

# Now the new checklist's join table entries look like the old checklist's entries did
# BEFORE the form was submitted; but I want to update the NEW Checklist so it reflects 
# the updates made in the form that was submitted.
# Part of the params[:checklist] has is "jobs_attributes", which is handled by
# accepts_nested_attributes_for. The problem is I can't really manipulate that hash very
# well, and I can't do a direct update with those attributes on my NEW model (as I'm 
# trying in the next line) due to a built-in limitation.
  @newChecklist.update_attributes(params[:checklist])

Y ahí es donde me encuentro con la limitación accept_nested_attributes_for (está bastante bien documentadoaquí. Obtengo la excepción "No se pudo encontrar el Modelo 1 con ID = X para el Modelo2 con ID = Y", que es básicamente como está diseñado.

Entonces, ¿cómo puedo crear múltiples modelos anidados y agregarlos / eliminarlos en la forma del modelo principal de manera similar a la que hace acepte_nated_attributes_for, pero por mi cuenta?

Las opciones que he visto, ¿es una de estas mejores?El verdadero truco es que necesito poder actualizar tanto los modelos existentes Y nuevos con las asociaciones / atributos existentes. No puedo vincularlos, así que los nombraré.

Redtape (en github) Virtus (también github)

¡Gracias por tu ayuda!

Respuestas a la pregunta(2)

Su respuesta a la pregunta