2011-02-02 14 views
5

Mam zadania i użytkowników. Gdy użytkownik wykona zadanie, utworzę Completion z polem, w którym użytkownik będzie mógł określić, ile czasu spędził. Potrzebuję formularza, który pokazuje wszystkie zadania ze statusem ukończenia i atrybutem time_spent. Po przesłaniu uzupełnienia, które istniały, powinny zostać zaktualizowane, a nowe powinny zostać utworzone. Chciałbym zrobić to w Formtastic, jeśli to możliwe, ale będę zadowolony z podstawowego rozwiązania Rails 3.Jak wyświetlić formularz dla podzestawu powiązanych rekordów, z których niektóre jeszcze nie istnieją?

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 

Dodatkowym aspektem jest to, że chcę pokazać tylko pewien zestaw zadań, takich jak te należące do Kamienia milowego. Czy powinienem mieć formularz kontrolera Milestone, który wysyła posty do kontrolera Completions?

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

UPDATE szukałem przez kilka dni teraz i znalazłem manydeadends. To jest blisko, ale wymaga to, że wszystkie obiekty łączące już istnieją.

To, co wyróżnia to pytanie, to że niektóre z linków jeszcze nie istnieją i nie ma jednego modelu dla linków do zagnieżdżenia. W przypadku Ryana Daigle'a Nested Object Forms post) wykonałem tę pracę w formie umożliwiającej edycję wszystkich możliwych uzupełnień dla użytkownika, ale muszę edytować podzbiór możliwych uzupełnień w jednym formularzu. Czy muszę wykonać redundantny obiekt MilestoneCompletions, który zawiera has_many Completions i belongs_to Użytkownik? Czy można ActiveModel has_many?

+2

Właśnie usunąłem moją odpowiedź, aby twoje pytanie było bardziej widoczne, edytuj swoje pytanie z danymi, które mi dałeś :) – apneadiving

+0

To bardzo przemyślane! Musiałem ominąć ten problem, więc w końcu zrezygnowałem i pracowałem nad tym. Opublikuję moją odpowiedź dla wszystkich zainteresowanych. – Turadg

Odpowiedz

4

W końcu to rozwiązałem. Jeden klucz to argument kolekcji do fields_for. Druga to generowanie kolekcji z połączeniem istniejących i nowych rekordów.

Tak więc w świetle, coś jak:

<%= 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 -%> 

Dzięki metodzie pomocnika:

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 

zawiadomienia w widoku Realizacje że już w DB są sprawdzane i wyłączone, więc nie mogą być odznaczone. Stan zaznaczone pobiera wartość „nieudokumentowanych” i model Użytkownik może odfiltrować te rekordy, żeby nie iść w DB:

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

miałem też dokonać completions_attributes attr_accessible na modelu użytkownika. Jeśli udostępnisz task_ids, wówczas update usunie uzupełnienia, które zostały pominięte w PUT.

0

Odpowiadam sobie za to, jako możliwe rozwiązanie dla innych czytelników, ale to nie jest satysfakcjonujące, więc nie oznaczam tego jako akceptowalnego.

Aby obejść ten problem, w akcji generowania formularzy wystarczy tylko brakujące skojarzenia w stanie "nieaktywnym". (Dodając pole status do modelu Completion.) Następnie używam funkcji edycji tablicy formularzy "object []". RISCfuture ma kilka pomocnych wskazówek w drugim komentarzu na temat the forms_for API docs.

Powiązane problemy