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

时间:2013-11-30 09:08:13

标签: ruby-on-rails activerecord rspec ruby-on-rails-3.2 filesystems

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

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

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

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

2 个答案:

答案 0 :(得分:1)

我感兴趣的非常有趣的问题,因为我目前正在开发一个上传和转换文件的应用程序。

根本不是RSpec的专家,但我认为它非常依赖于数据库,如果它与数据库无关(如创建文件夹/更新),则由用户自行清理图像/启动外部接口)。

找到关于如何使用after(:all)进行清理with RSepc and carrierwave testing的示例 - 与我的初始类似。

另一种选择是更务实,在测试方面可能更有限。 为目标结构提供备份文件,并在测试完成后将其恢复。

如果有人有更好的方法,我确实感兴趣。

希望这有帮助! 欧根

答案 1 :(得分:1)

如果通过ActiveRecord创建,销毁或更新记录,则只会调用已定义的after_rollback回调。当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

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

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

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

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

#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

希望有所帮助。