Ассоциация автосохранения Rails в действии контроллера - PullRequest
2 голосов
/ 10 марта 2010

У меня есть следующая связь со многими. В документе много разделов, а в разделе много элементов.

class Document < ActiveRecord::Base
  has_many :document_sections, :dependent => :destroy, :autosave => true
  has_many :document_items, :through => :document_sections
end

class DocumentSection < ActiveRecord::Base
  belongs_to :document
  has_many :document_items, :dependent => :destroy, :autosave => true
end

class DocumentItem < ActiveRecord::Base
  belongs_to :document_section
end

Вот хэш параметров:

-
Parameters: {"commit"=>"Submit Document", "authenticity_token"=>"4nx2B0pJkvavDmkEQ305ABHy+h5R4bZTrmHUv1setnc=", "id"=>"10184", "document"=>{"section"=>{"10254"=>{"seqnum"=>"3", "item"=>{"10259"=>{"comments"=>"tada"}}}}, "comment"=>"blah"}}

У меня есть следующий метод обновления ...

# PUT /documents/1                                                                                                                                                 
# PUT /documents/1.xml




def update
    @document = Document.find(params[:id])

    # This is header comment
    @document.comment = params[:document][:comment]

    params[:document][:section].each do |k,v|
       document_section =  @document.document_sections.find_by_id(k)
       if document_section

          v[:item].each do |key, value|
             document_item = document_section.feedback_items.find_by_id(key)
             if document_item

                # This is item comments
                document_item.comments = value[:comments]
             end
          end

       end
     end

    @document.save

  end

Когда я сохраняю документ, он обновляет только комментарии заголовка документа. Это не сохраняет комментарии document_item. Не должна опция автосохранения также обновлять ассоциации.

В журнале зарегистрирован только следующий DML:

UPDATE documents SET updated_at = TO_DATE('2010-03-09 08:35:59','YYYY-MM-DD HH24:MI:SS'), comment = 'blah' WHERE id = 10184

Как сохранить ассоциации, сохранив документ.

1 Ответ

2 голосов
/ 10 марта 2010

Мне кажется, я вижу в чем проблема. Я уверен, что вы не можете сделать следующее:

# Triggers a database call
document_section =  @document.document_sections.find_by_id(k)

И ожидать, что ActiveRecord сохранит связь для автосохранения. Вместо этого вы должны сохранять загруженные записи по отдельности. Что, конечно, не было бы атомным.

Я полагаю, что автосохранение работает так, как вы думаете, вы хотите сделать что-то вроде этого:

# untested...
@document.document_sections.collect { |s| s.id == k }.foo = "bar"

Обратите внимание, что здесь я на самом деле изменяю фиктивный параметр foo в массиве вместо вызова find_by_id, который будет повторно запрашивать базу данных и возвращать новый объект.

Третий вариант, который у вас есть, состоит в том, что вы, конечно, можете делать то, что изначально планировали, но обрабатывать все транзакции самостоятельно или использовать вложенные транзакции и т. Д., Чтобы получить безопасные данные. Это было бы необходимо, если бы ваши данные были слишком большими для работы с массивами, поскольку автоматическое сохранение по своей природе запускает загрузку всех связанных данных в память.

Все зависит от вашего приложения.


Некоторые разъяснения по основной проблеме:

Если вы запускаете метод find_by_id, вы просите ActiveRecord вернуть вам новый набор объектов, соответствующих этому запросу. Тот факт, что вы выполнили этот метод из экземпляра (document_sections), на самом деле является еще одним способом сказать:

DocumentSection.find_by_id(k)

Вызывать его из экземпляра объекта, я думаю, это просто некоторая синтаксическая привлекательность, которую рельсы добавляют в начало, но, на мой взгляд, это не имеет большого смысла; Я думаю, что это может быть удобно в некоторых приложениях, я не уверен.

С другой стороны, collect - это метод Ruby Array, который предлагает способ «разрезать» массив с помощью блока. В основном модный цикл foreach. :) При непосредственном взаимодействии с массивом document_sections вы изменяете те же объекты, которые уже были загружены в содержащий объект (@document), которые затем будут зафиксированы при save со специальным флагом autosave.

НТН! Рад, что ты вернулся и бежишь. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...