Rails:为什么这个marked_for_destruction没有被破坏?

时间:2013-03-01 16:40:05

标签: ruby-on-rails ruby-on-rails-3 rails-activerecord

**更新** 这一切似乎与自定义验证器有关:如果我删除它,它按预期工作。最后看代码 **

我的模型budget有很多multi_year_impacts

在控制台中,如果我运行:

b = Budget.find(4)
b.multi_year_impacts.size #=> 2
b.update_attributes({multi_year_impacts_attributes: {id: 20, _destroy: true} } ) #=> true
b.multi_year_impacts.size #=> 1 (so far so good)
b.reload
b.multi_year_impacts.size #=> 2 What???

如果在b.reload之前{I} b.save(无论如何都不需要),它也是一样的。

知道为什么我的孩子记录不会被破坏?

一些其他信息,以防万一:

Rails 3.2.12

budget.rb

中的

attr_accessible :multi_year_impacts_attributes
has_many :multi_year_impacts, as: :impactable, :dependent => :destroy
accepts_nested_attributes_for :multi_year_impacts, :allow_destroy => true
validates_with MultiYearImpactValidator # problem seems to com from here
multi_year_impact.rb

中的

belongs_to :impactable, polymorphic: true
multi_year_impact_validator.rb

中的

class MultiYearImpactValidator < ActiveModel::Validator
  def validate(record)
    return false unless record.amount_before && record.amount_after && record.savings        
    lines = record.multi_year_impacts.delete_if{|x| x.marked_for_destruction?}

    %w[amount_before amount_after savings].each do |val|
      if lines.inject(0){|s,e| s + e.send(val).to_f} != record.send(val)
        record.errors.add(val.to_sym, " please check \"Repartition per year\" below: the sum of all lines must be equal of total amounts")
      end
    end

  end
end

2 个答案:

答案 0 :(得分:0)

它可能取决于您的rails版本,但是,将您的代码与当前docs

进行比较
  

现在,当您将_destroy键添加到属性哈希时,使用   如果计算结果为true,则会销毁关联的模型:

member.avatar_attributes = { :id => '2', :_destroy => '1' }
member.avatar.marked_for_destruction? # => true 
member.save
member.reload.avatar # => nil
     

请注意,在保存父项之前不会销毁模型。

你可以试试:

b.multi_year_impacts_attributes =  {id: 20, _destroy: true}
b.save

答案 1 :(得分:0)

所以看起来罪魁祸首就在这里

if lines.inject(0){|s,e| s + e.send(val).to_f} != record.send(val)
    record.errors.add(val.to_sym, " please check \"Repartition per year\" below: the sum of all lines must be equal of total amounts")
end

将此更改为稍微复杂的

  total = 0
  lines.each do |l|
    total += l.send(val).to_f unless l.marked_for_destruction?
  end
  if total != record.send(val)
    record.errors[:amount_before] << " please check \"Repartition per year\" below: the sum of all lines must be equal of total amounts"
  end

解决了这个问题。