2011-02-02 5 views
5

Tengo tareas y usuarios. Cuando un usuario completa una tarea, creo una finalización que tiene un campo para que el usuario indique cuánto tiempo pasó. Necesito un formulario que muestre todas las tareas con su estado de finalización y el atributo time_spent. En el envío, las terminaciones que existen deben actualizarse y deben crearse nuevas. Me gustaría hacer esto en Formtastic si es posible, pero estaré contento con una solución básica de Rails 3.¿Cómo mostrar un formulario para un subconjunto de registros asociados, algunos de los cuales aún no existen?

class Completion < ActiveRecord::Base 
    belongs_to :task 
    belongs_to :user 

    # attribute time_spent 
end 

class User < ActiveRecord::Base 
    has_many :completions 
    has_many :tasks, :through => :completions 
end  

class Task < ActiveRecord::Base 
    belongs_to :milestone 
    has_many :completions 
    has_many :users, :through => :completions 
end 

Un aspecto adicional es que quiero mostrar solo un cierto conjunto de tareas, como las pertenecientes a un Milestone. ¿Debo tener un formulario en el controlador Milestone que se publique en el controlador de finalizaciones?

class Milestone < ActiveRecord::Base 
    has_many :tasks 
    has_many :completions, :through => :tasks 
end 

ACTUALIZACIÓN he buscado desde hace días y he encontrado manydeadends. Este Multiple objects in a Rails form está cerca, pero requiere que todos los objetos de enlace ya existan.

Lo que diferencia esta pregunta es que algunos de los enlaces aún no existen y no hay un solo modelo para anidar los enlaces. P. ej. Con Ryan Daigle's Nested Object Forms post) he hecho que esto funcione para editar todas las terminaciones posibles para un usuario, pero necesito editar un subconjunto de posibles terminaciones en un formulario. ¿Necesito hacer un objeto redundante MilestoneCompletions que has_many Completions y belongs_to Usuario? ¿Puede un ActiveModel has_many?

+2

acaba de eliminar mi respuesta para que su pregunta sea más visible, edite su pregunta con los detalles que me dio :) – apneadiving

+0

¡Eso es muy considerado! Tuve que superar este problema, así que finalmente me di por vencido y trabajé en torno a eso. Voy a publicar mi respuesta para cualquier persona interesada. – Turadg

Respuesta

4

Finalmente resolví esto. Una clave es el argumento de recopilación al fields_for. El otro es generar la colección con una combinación de registros existentes y nuevos.

Así que en la vista, algo así como:

<%= form_for @user do |f| %> 
    <table> 
    <tr><th>Completed</th><th>Time spent</th><th>Task</th></tr> 

    <%= f.fields_for :completions, available_completions_for_milestone(@user, @milestone) do |cf| %> 
     <tr> 
     <td><%= cf.check_box :status, {disabled: cf.object.persisted?}, "done", "unreported" %></td> 
     <td><%= cf.text_field :time_spent_text %></td> 
     <td><%= cf.object.task.description %></td> 
     </tr> 
     <%= cf.hidden_field :task_id %> 
    <% end -%> 

Con un método de ayuda:

def available_completions_for_milestone(user, milestone) 
    user_completions = user.completions.in_milestone(milestone)  
    available = [] 
    milestone.tasks.each do |t| 
    c = user_completions.select{|c| c.task_id == t.id}.first 
    if !c then # make it 
     c = user.completions.build(task: t) 
    end 
    available << c 
    end 
    available 
end 

Aviso en la vista que ya terminaciones en la base de datos se comprueban y personas con discapacidad para que no puedan ser desmarcado El estado sin control obtiene el valor "no declarada" y el modelo de usuario puede filtrar los registros para que no se vaya en el PP:

has_many :completions 
accepts_nested_attributes_for :completions, :reject_if => proc { |attrs| attrs['status'] == 'unreported' } 

También tuve que hacer completions_attributes attr_accessible en el modelo de usuario. Si hace task_ids accesible, entonces update eliminará las terminaciones que quedaron fuera del PUT.

0

Estoy respondiendo a esto yo mismo como una posible solución para otros lectores, pero no es satisfactorio, así que no lo estoy marcando como aceptable.

Para solucionar esto, en la acción de generación de formularios acabo de create cualquier asociación faltante en un estado 'inactivo'. (Al agregar un campo status al modelo Completion). Luego uso la función de edición de matriz "object []" de formularios. RISCfuture tiene algunos consejos útiles en el segundo comentario en the forms_for API docs.

Cuestiones relacionadas