【问题标题】:update_attributes does not update nested_attributes in some casesupdate_attributes 在某些情况下不会更新嵌套属性
【发布时间】:2013-01-01 22:32:10
【问题描述】:

我正在使用 rails 3.2.8 编写一个小的 CMS 应用程序。段落(基本上包含例如新闻文章的标题、正文和日期)和页面(由许多段落组成,例如许多新闻文章)有一个模型。以下内容仅在日期更改的情况下更新段落,否则该段落不会更新,即使例如身体变了!?

page.update_attributes({"paragraphs_attributes"=>{"0"=>{"_destroy"=>"0", 
             "title"=>"News title", "body"=>"News text", "id"=>"4", 
             "date(3i)"=>"1", "date(2i)"=>"1", "date(1i)"=>"2013"}}})

您可以在下面找到模型的相关部分:

page.rb

class Page < ActiveRecord::Base
  has_many :paragraphs, :dependent => :destroy
  attr_accessible :name, :paragraphs_attributes
  accepts_nested_attributes_for :paragraphs, :allow_destroy => true
end

段落.rb

class Paragraph < ActiveRecord::Base
  belongs_to :page
  attr_accessible :title, :body, :page, :date
  validates :page,  presence: true
end

有人知道这种奇怪行为的原因吗?

【问题讨论】:

    标签: ruby-on-rails date update-attributes


    【解决方案1】:

    当然也有可能是一个肮脏的解决方法:在最终更新之前插入一个假更新。请注意,这是一种非常糟糕的风格,并且更新的数据库访问量增加了一倍,但由于我找不到其他解决方案,我想出了以下解决方案:

    page_controller.rb

    class PageController < ApplicationController
    
      def update
    
        # Hack: Updating paragraphs fails for some strange reasons if their date 
        # did not change. Updating paragraphs with date changes works as expected.
        # To allow updates in all cases, we first make an update to an impossible
        # date and then make an update to the real date.
    
    
        # Define a year, that will never occure in the params.
        # This date will be used for the fake update.
        impossible_year = "1999"
    
        # Setup the fake params for the first fake update (Change the date fields of 
        # all paragraphs to an impossible date).
        fake_params = params[:page].deep_dup
        par_attrs = fake_params[:paragraphs_attributes]
        par_attrs.keys.each do |key|
          par_attrs[key]["date(1i)"] = impossible_year
        end
    
        # Perform the fake update.
        @page.update_attributes(fake_params)
    
        # Finally do the real update with the original params.
        @page.update_attributes(params[:page])
      end
    end
    

    【讨论】:

      【解决方案2】:

      https://github.com/rails/rails/blob/d32965399ccfa2052a4d52b70db1bae0ca16830b/activerecord/lib/active_record/nested_attributes.rb#L72

      检查语法

         # Now, when you add the <tt>_delete</tt> key to the attributes hash, with a
          # value that evaluates to +true+, you will destroy the associated model:
          #
          #   member.avatar_attributes = { :id => '2', :_delete => '1' }
          #   member.avatar.marked_for_destruction? # => true
          #   member.save
          #   member.avatar #=> nil
      

      【讨论】:

        猜你喜欢
        • 2020-05-04
        • 2023-03-21
        • 1970-01-01
        • 2015-09-15
        • 2019-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-04
        相关资源
        最近更新 更多