如何定义allow_destroy和:dependent => : 在 Rails 中销毁?

发布于 2024-10-25 00:37:02 字数 2256 浏览 3 评论 0原文

给定以下数据库模型,您将如何以及在何处定义模型之间的删除关系?我弄清楚了基本的表关联设置,但是当我想添加依赖项以启用删除嵌套对象时,我迷失了。

数据库关系模型

这是我创建的关系模型。

class User < ActiveRecord::Base
  has_many :studies
end

class Study < ActiveRecord::Base
  has_many :internships
  belongs_to :student, :class_name => "User", :foreign_key => "user_id"
  belongs_to :subject
  belongs_to :university, :class_name => "Facility", :foreign_key => "facility_id"
  accepts_nested_attributes_for :subject, :university, :locations
end

class Subject < ActiveRecord::Base
  has_many :studies
end

class Internship < ActiveRecord::Base
  belongs_to :study
  belongs_to :company, :class_name => "Facility", :foreign_key => 'facility_id'
  accepts_nested_attributes_for :company, :study
end

class Facility < ActiveRecord::Base
  has_many :internships
  has_many :locations
  has_many :studies
  accepts_nested_attributes_for :locations
end

class Location < ActiveRecord::Base
  belongs_to :facility
end

你会把 :dependent => 放在哪里:destroy:allow_destroy => true 启用以下场景?我不想让你感到困惑。因此,我省略了我的尝试。

实习场景:用户想要删除实习。

  • 如果该公司与其他实习无关,则可以删除其关联公司(设施)。
  • 如果是这样,则可以删除关联公司的位置。
  • 相关研究不会受到影响。

研究场景:用户想要删除一项研究。

  • 如果没有其他研究引用该主题,则可以删除其相关主题。
  • 如果没有其他研究提及该大学,则可以删除其关联大学(设施)。
  • 其关联的实习可以删除。只有在没有其他实习涉及该公司的情况下才能删除该公司。

我完全不确定是否可以添加 :dependent =>; :destroy 仅在 has_onehas_many 之后或在 belongs_to 之后。


编辑:为了简化问题,请坚持以下(简化的)示例实现。

class Study < ActiveRecord::Base
  belongs_to :subject
  accepts_nested_attributes_for :subject, :allow_destroy => true
end

class Subject < ActiveRecord::Base
  has_many :studies, :dependent => :destroy
end

在我看来,我提供以下链接。

<%= link_to "Destroy", study, :method => :delete, :confirm => "Are you sure?" %>

该路径基于 routes.rb 中的静态配置给出的命名路由。

resources :studies
resources :subjects

当我点击链接时,该研究将被删除 - 受试者保持不变。为什么?

Given the following database model, how and where would you define the deletion relationships between the models? I figured out the basic table association setup but when I want to add dependencies to enable the deletion of nested objects I get lost.

Database relationship model

Here is the relationship model I created.

class User < ActiveRecord::Base
  has_many :studies
end

class Study < ActiveRecord::Base
  has_many :internships
  belongs_to :student, :class_name => "User", :foreign_key => "user_id"
  belongs_to :subject
  belongs_to :university, :class_name => "Facility", :foreign_key => "facility_id"
  accepts_nested_attributes_for :subject, :university, :locations
end

class Subject < ActiveRecord::Base
  has_many :studies
end

class Internship < ActiveRecord::Base
  belongs_to :study
  belongs_to :company, :class_name => "Facility", :foreign_key => 'facility_id'
  accepts_nested_attributes_for :company, :study
end

class Facility < ActiveRecord::Base
  has_many :internships
  has_many :locations
  has_many :studies
  accepts_nested_attributes_for :locations
end

class Location < ActiveRecord::Base
  belongs_to :facility
end

Where would you put :dependent => :destroy and :allow_destroy => true to enable the following scenarios? I do not want to confuse you. Therefore, I leave out my tryings.

Internship scenario: A user wants to delete an internship.

  • Its associated company (facility) can be deleted if the company is not related to another internship.
  • If so, the locations of the associated company can be deleted.
  • The related study will not be affected.

Study scenario: A user wants to delete a study.

  • Its associated subject can be deleted if no other study refers to this subject.
  • Its associated university (facility) can be deleted if no other study refers to this university.
  • Its associated internships can be deleted. The company can only be deleted if no other internship refers to it.

I am totally unsure whether I can add :dependent => :destroy only after has_one and has_many or also after belongs_to.


Edit: To simplify the problem please stick to the following (reduced) example implementation.

class Study < ActiveRecord::Base
  belongs_to :subject
  accepts_nested_attributes_for :subject, :allow_destroy => true
end

class Subject < ActiveRecord::Base
  has_many :studies, :dependent => :destroy
end

In my view I provide the following link.

<%= link_to "Destroy", study, :method => :delete, :confirm => "Are you sure?" %>

The path is based on the named routes given by a restful configuration in routes.rb.

resources :studies
resources :subjects

The study will be deleted when I click the link - the subjects stays untouched. Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

叹倦 2024-11-01 00:37:02

我认为你们的关系在这里是错误的......
应在 has_many 所属模型的 has_many 模型上声明 accepts_nested_attributes_for。此外,在您的示例中,销毁主题将对许多研究强制执行dependent_destroy,而不是相反。

I think your relations are the wrong way around here...
The accepts_nested_attributes_for should be declared on the model that has_many for the model that it has_many of. Also, in your example, destroying the subject would enforce dependent_destroy on the many studies, not the other way around.

維他命╮ 2024-11-01 00:37:02

您可以添加 :dependent =>; :destroy 对所有三个,但我不确定这是否会给您足够的权力来在确定是否应销毁关联对象之前执行所需的检查。

你有几个选择。

在每个模型上添加 before_destroy 回调,以引发异常或阻止删除发生。

class Facility < ActiveRecord::Base
  has_many :internships
  has_many :locations
  has_many :studies

  def before_destroy
    raise SomethingException if internships.any? || ...
    # or
    errors.add(...
  end
end

或者通过重写 destroy 来默默地执行此操作

class Facility < ActiveRecord::Base
  has_many :internships
  has_many :locations
  has_many :studies

  def destroy
    return false if internships.any || ...
    super
  end
end

注意:这基本上仅用于指导,可能不是重写 destroy 等的正确方法...

You can add :dependent => :destroy to all three but I'm not sure if that'll give you enough power to do the checks required before determining whether an associated object should be destroyed.

You have a few options.

Add a before_destroy callback on each model that raises an exception or stops the delete from occurring.

class Facility < ActiveRecord::Base
  has_many :internships
  has_many :locations
  has_many :studies

  def before_destroy
    raise SomethingException if internships.any? || ...
    # or
    errors.add(...
  end
end

or do it silently by overriding destroy

class Facility < ActiveRecord::Base
  has_many :internships
  has_many :locations
  has_many :studies

  def destroy
    return false if internships.any || ...
    super
  end
end

Note: this is basically meant for guidance only and may not be the correct way of overriding destroy etc...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文