【问题标题】:Ruby on Rails: Better approach to delete related modelsRuby on Rails:删除相关模型的更好方法
【发布时间】:2012-01-25 23:05:57
【问题描述】:

我定义了以下类/关系:

class Component < ActiveRecord::Base
    has_many :component_stories,:dependent => :destroy
    has_many :stories, :through => :component_stories
end

class Story < ActiveRecord:Base
    has_many :component_stories,:dependent => :destroy
    has_many :components, :through => :component_stories
end

class ComponentStory < ActiveRecord::Base
    belongs_to :component
    belongs_to :story
end

假设我们有 2 个故事的组件 1:故事 1 和故事 2。 story2 也属于 component2。如果我们删除 component1,story1 将被永久删除,但 story2 仍然属于 component2。我在组件模型中定义了一个方法来删除与任何其他组件无关的故事:

def delete_dependent_stories
   stories.each do |story|
     if story.component_stories.size == 1
       story.destroy
     end
   end
end

此方法将在 components_controller 的销毁操作中调用:

def destroy
   component = Component.find(params[:id])
   component.delete_dependent_stories
   component.destroy
   ...
end

这样,我确保没有与任何组件无关的“僵尸”故事。我担心是否有更好的方法来替代组件模型中的该方法。

【问题讨论】:

  • 看起来不错 - 我只是将 delete_dependent_stories 方法移动到组件模型中的 before_destroy 回调
  • if story.component_stories.size == 1 story.destroy end 在并发环境中无法正常工作。考虑当我们有两个组件 c1 和 c2 的故事,并且两个用户同时删除这些组件时的情况。 if 语句在这种情况下返回 false(因为 story.component_storues.size 实际上等于 2),没有人删除该故事,并且 - 瞧 - 你有一个僵尸。
  • 顺便说一句,类似的问题:stackoverflow.com/questions/5546001/…
  • 将其包装在事务中
  • after_destroy 回调会比 before_destroy 更好,因为这样您就可以保证它只会在第一个对象被销毁时发生。

标签: ruby-on-rails ruby model relationship


【解决方案1】:

您应该像这样利用模型回调:

class Component < ActiveRecord::Base
  has_many :component_stories,:dependent => :destroy
  has_many :stories, :through => :component_stories

  after_destroy :delete_dependent_story?

  private

  def delete_dependent_stories
    stories.each do |story|
      if story.has_component_stories?
        story.destroy
      end
  end
end

class Story < ActiveRecord:Base
  has_many :component_stories,:dependent => :destroy
  has_many :components, :through => :component_stories

  self.has_component_story?
    component_stories.size == 1
  end
end

不要使用before_destroy,因为无论是否成功删除component,它都会删除story

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多