保持模型记录和相关目录同步(与测试)

Bre*_*uir 9 filesystems activerecord rspec ruby-on-rails ruby-on-rails-3.2

在我的应用程序中,我在创建主题记录时创建了一个目录.这是为了存储与主题相关的文件资产.我一直在努力避免如何使目录的存在与记录的生命周期保持同步.这是我目前的看法:

after_create :create_theme_directory
after_rollback :destroy_theme_directory, :on => :create, :if => :id

def directory
    Rails.configuration.uploads_root.join('themes', id.to_s)
end

private

def create_theme_directory
    FileUtils.mkdir_p directory
end

def destroy_theme_directory
    FileUtils.remove_dir directory, :force => true
end
Run Code Online (Sandbox Code Playgroud)

它运行良好,但Rspec在测试后回滚主题记录时似乎没有触发删除目录.

这种事情有最好的做法吗?我们的想法是永远不要留下没有相关记录的迷路目录.

Gja*_*don 1

after_rollback仅当创建、销毁或更新记录是通过 ActiveRecord 完成时,才会调用您定义的回调。当 RSpec 重置时,它不会通过 ActiveRecord,因此不会触发任何事务回调(after_rollback 和 after_commit)。

您可以添加另一个回调来销毁该目录(如果该目录仍然存在):

after_commit :destroy_theme_directory, :on => :destroy

def destroy_theme_directory
  if File.directory?(directory)
    FileUtils.remove_dir directory, :force => true
  end
end
Run Code Online (Sandbox Code Playgroud)

然后触发功能规范中的创建和销毁操作:

scenario 'create and destroy' do
  visit new_directory_path
  #fill_in fields
  click_button "Create"

  expect(page).to have_content "created"

  visit users_path
  click_link "Delete" #assuming only directory object exists and you have a delete link in your directory index page
end
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以触发规范中的创建和销毁操作,因此您无需进行任何清理。

另一个选项是手动删除规范中测试其创建的目录。

#assuming you have model spec for testing that directory is created
it 'creates corresponding directory'
  directory.create
  expect(File.directory?(directory)).to eq true

  # the line below is just for cleanup. No need to do it in an after_all block if it only needs to be done for a few specs
  FileUtils.remove_dir directory, :force => true 
end
Run Code Online (Sandbox Code Playgroud)

希望有帮助。