开发者

Rails autosave association in controller action

开发者 https://www.devze.com 2022-12-22 16:43 出处:网络
I have the following one to many associations. Document has many Sections and Section has many Items.

I have the following one to many associations. Document has many Sections and Section has many Items.

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

Here is the params hash:

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

I have the following update method...

# 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

Wh开发者_C百科en I save the document it only updates the document header comments. It does not save the document_item comments. Shouldn't the autosave option also update the associations.

In the log only the following DML is registered:

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

How do I save the associations by saving the document.


I think I see what the problem is. I'm pretty sure that you cannot do the following:

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

And expect ActiveRecord to keep the association for autosaves. Instead, you should save the loaded records individually. Which of course would not be atomic.

I believe for autosave to work like you are thinking, you want to do something like this:

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

Notice that here I'm actually modifying a fake param foo in the array, instead of calling find_by_id, which will re-query the database and return a new object.

A third option you have is that you could of course, do what you had originally planned, but handle all the transactions yourself, or use nested transactions, etc, to get the atmoic saves. This would be necessary if your data was too large for array manipulation to work since autosave by it's natures triggers a load of all associated data into memory.

It all depends on your application.


Some clarifications on the underlying problem:

If you run the find_by_id method, you are asking ActiveRecord to return to you a new set of objects that match that query. The fact that you executed that method from an instance (document_sections) is really just another way of saying:

DocumentSection.find_by_id(k)

Calling it from an object instance I think is just some syntactic niceness that rails is adding on the top of things, but in my mind it doesn't make a lot of sense; I think it could be handy in some application, I'm not sure.

On the other side, collect is a Ruby Array method that offers a way to "slice" an array using a block. Basically a fancy foreach loop. :) By interacting with the document_sections array directly, you are changing the same objects already loaded into the containing object (@document), which will then be committed when you save with the special autosave flag set.

HTH! Glad you are back and running. :)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号