【问题标题】:ActiveRecord many to many associations behavior after destroyActiveRecord 销毁后的多对多关联行为
【发布时间】:2015-07-02 17:53:38
【问题描述】:

我有一个模型数据库:AppContentCategory
每个应用可以有多个内容类别,反之亦然。

另外,我的连接表为ContentCategoryOwnership

class ContentCategory < ActiveRecord::Base
    has_many :content_category_ownerships, inverse_of: :content_category, dependent: :destroy
    has_many :apps, through: :content_category_ownerships
    attr_accessible(
        :title
        )
    validates :title, uniqueness: :true
end

class App < ActiveRecord::Base
  has_many :app_targetings, inverse_of: :app
  has_many :campaigns, through: :app_targetings
  has_many :app_ownerships
  has_many :users, through: :app_ownerships


  has_many :content_category_ownerships, inverse_of: :app, dependent: :destroy
  has_many :content_categories, through: :content_category_ownerships
end

class ContentCategoryOwnership < ActiveRecord::Base
    belongs_to :content_category
    belongs_to :app
    has_many :content_category_targetings, inverse_of: :content_category_ownership, dependent: :destroy
end

it 'is expected to be deleted consistently' do
    fashion = create :content_category, title: 'fashion'
    motors = create :content_category, title: 'motors'
    app = create :app
    another_app = create :app
    app.content_categories << [fashion, motors]
    another_app.content_categories << fashion

    fashion.destroy
    expect(fashion).to be_destroyed

    expect(app.content_categories).to contain_exactly(motors) # not removed?
    expect(another_app.content_categories).to be_empty # not removed? ( empty - false, still contains fashion category )
    expect(another_app.content_categories.pluck(:title)).to be_empty # true!
end

我将行为视为“缓存”关联结果。因此,如果您不理会关联another_app.content_categories,您将看到此关联仍然包含已删除的对象(fashion 类别)。如果添加例如pluck 方法,您将看到空结果。

我需要解释一下这种行为,也许我错过了文档点。

Rails 控制台示例:

 app = App.new
 app.id = 42
 content_category = ContentCategory.new
 content_category.id = 42
 app.content_categories << content_category
 app.content_categories
 content_category.destroy
 app.content_categories.empty? # ( false )
 app.content_categories # still exists?
 app.content_categories.pluck(:id).empty? # true!

信息:

  • 活动记录 4.2.1
  • Rails 4.2.1
  • Ruby 2.2.2

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    这里的问题是content_categories 缓存在appanother_app 的实例中,当您销毁它们时,缓存不会反映此更改。

    你需要做的是reload对象例如

    it 'is expected to be deleted consistently' do
        fashion = create :content_category, title: 'fashion'
        motors = create :content_category, title: 'motors'
        app = create :app
        another_app = create :app
        app.content_categories << [fashion, motors]
        another_app.content_categories << fashion
    
        fashion.destroy
        expect(fashion).to be_destroyed
        app.reload
        another_app.reload
        expect(app.content_categories).to contain_exactly(motors) # removed
        expect(another_app.content_categories).to be_empty #removed
        expect(another_app.content_categories.pluck(:title)).to be_empty 
    end
    

    pluck 起作用的原因是它不依赖于缓存的值,而是对数据库运行查询以提取标题,当它检查数据库时,不再有任何带有app_idContentCategories匹配给定实例id

    【讨论】:

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