Rails 4 has_many:through relationship:当子模型实例计数达到0时销毁父模型实例

时间:2015-07-09 18:58:49

标签: ruby-on-rails ruby-on-rails-4 activerecord model-view-controller has-many-through

在我们的Rails 4应用程序中,有四种模式:

Clone()

以下是相应的迁移:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
  has_many :posts, dependent: :destroy
end

class Post < ActiveRecord::Base
    belongs_to :calendar
end

每次class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :first_name t.string :last_name t.string :email t.integer :total_calendar_count t.integer :owned_calendar_count t.timestamps null: false end end end class CreateAdministrations < ActiveRecord::Migration def change create_table :administrations do |t| t.references :user, index: true, foreign_key: true t.references :calendar, index: true, foreign_key: true t.string :role t.timestamps null: false end end end class CreateCalendars < ActiveRecord::Migration def change create_table :calendars do |t| t.string :name t.timestamps null: false end end end class CreatePosts < ActiveRecord::Migration def change create_table :posts do |t| t.references :calendar, index: true, foreign_key: true t.date :date t.time :time t.string :focus t.string :format t.string :blog_title t.text :long_copy t.text :short_copy t.string :link t.string :hashtag t.string :media t.float :promotion t.string :target t.integer :approval t.text :comment t.timestamps null: false end end end 退出user,意味着我们calendar相应的destroy,我们希望确保发生以下情况:

  • 我们检查相同的administration是否还有其他administrations
  • 如果有,我们什么都不做(用户只是被重定向到他的仪表板)。
  • 但如果还没有(例如,因为用户是最后一个退出日历的人),那么我们也想销毁日历。
  • 这应该会自动销毁属于此日历的所有帖子,这要归功于我们calendar模型中的has_many :posts, dependent: :destroy行,但我们认为检查它也不会有害。

我们正在考虑通过Calendar模型中的private clear_calendar方法实现此目标,我们将在Calendar控制器中将其用作after_destroy回调:

Administrations

这有意义吗?

1 个答案:

答案 0 :(得分:2)

这是一种非常明智的方法,整个世界都很高兴您没有将此逻辑置于控制器动作中。

有一点需要注意:通过将此逻辑放在Calendar模型中,您必须将CalendarAdministration绑定在一起。也许你觉得在这个时候还不错,但是一个真正的面向对象的程序,而不是询问另一个模型是否存在,而是告诉模型它想要什么而不是如何它想要它完成(例如,如果这种关联不存在,则删除self。)

我建议将此逻辑放在PORO中 - 也许是一种服务 - 从数据库支持的对象中删除不必要的耦合。也许这看起来像是这样的:

class Calendar < ActiveRecord::Base

...

private

  def clear_calendar
    ParentDestructionService.new(self)
  end

end


class ParentDestructionService
  def initialize(parent)
    @parent = parent
  end

  .....logic goes here.....
end

通过这种方式,您不仅可以将如何流程与不应该关注Administration的类分开,而且您现在可以将其添加到Sidekiq进程,或简单地将其断开。无论哪种方式,您都会变得更加灵活。现在,将来,您将能够通过该服务发送任何父级,并且事情将按预期发挥作用。