2

仅当它们更改时才使用 deploy.rb 预编译 Rails 资产,此任务总是跳过我的资产的编译:(

namespace :assets do
  task :precompile, :roles => :web, :except => {:no_release => true} do
    from = source.next_revision(current_revision)
    if capture("cd #{latest_release} && #{source.local.log(from)} vendor/assets/ app/assets/ | wc -l").to_i > 0
      run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}
    else
      logger.info "Skipping asset pre-compilation because there were no asset changes"
    end
  end
end

什么可能导致这个完整的任务无法编译?它始终认为没有资产更改并抛出该消息。

我也从来没有真正理解过这个任务,例如下面的 source.log.local 指的是什么?

source.local.log

任何人都可以澄清任务命令的作用,并有一些指示为什么它永远不会看到任何资产变化?谢谢

4

1 回答 1

17

它能做什么:

from = source.next_revision(current_revision)

source是对您的源代码的引用,从您的 SCM(git、svn 等)可以看出。这设置from为(本质上)源代码的当前部署版本。

capture("cd #{latest_release} && #{source.local.log(from)} vendor/assets/ app/assets/ | wc -l")

capture意思是“在 shell 中执行这个命令,并返回它的输出”。有问题的命令引用了对您的源的更改日志,将部署的版本与当前版本进行比较(将资产所在的路径指定为“重要”的路径),并将其传递到字数统计工具 ( wc -l)。该-l选项意味着它返回输出中行数的计数。因此,输出(由 返回capture)是在这两个版本之间发生更改的文件名的数量。

如果该数字为零,则任何指定路径中的文件都没有更改,因此我们跳过预编译。

为什么它不起作用:

我不知道。代码本身似乎没有任何问题 - 它或多或少与我使用的代码段相同。您可以检查以下几件事:

  1. Capistrano 是否知道您正在使用资产管道?检查您的 Capfile。如果你没有load 'deploy/assets',部署甚至不会考虑编译你的资产。

  2. 事实上,您是否启用了资产管道?检查 application.rbconfig.assets.enabled = true

  3. 您是否指定了不正确的资产路径?该代码正在检查 和 中的vendor/assets/更改app/assets/。如果您的资产位于其他地方(lib/assets例如 ),它们将不会被注意到。(如果是这种情况,您可以更改该行以包含正确的路径。

  4. 事实上,自上次部署以来,您是否更改了任何资产?我建议绕过检查更改资产并强制预编译运行一次,然后重新打开检查并看到问题神奇地自行解决。在下面的示例中,设置force_precompile = true可以做到这一点。

我用什么:

这是我目前使用的版本。这可能会有所帮助。或不。与原作的变化:

  1. 一种更易读的方式来指定资产路径(如果您使用它,请记住设置asset_locations为您的资产所在的位置)
  2. 一种强制预编译运行的简单方法(设置force_precompile=true为尝试运行检查,但无论如何都运行预编译)
  3. 无论预编译是否运行,它都会打印出计数。我很高兴获得一些输出以确保检查正在运行。
  4. 如果在尝试比较文件时发生错误(例如,在全新项目中经常发生),它会打印错误但无论如何都会运行预编译。

.

  namespace :assets do
    task :precompile, :roles => :web, :except => { :no_release => true } do
      # Check if assets have changed. If not, don't run the precompile task - it takes a long time.
      force_compile = false
      changed_asset_count = 0
      begin
        from = source.next_revision(current_revision)
        asset_locations = 'app/assets/ lib/assets vendor/assets'
        changed_asset_count = capture("cd #{latest_release} && #{source.local.log(from)} #{asset_locations} | wc -l").to_i
      rescue Exception => e
        logger.info "Error: #{e}, forcing precompile"
        force_compile = true
      end
      if changed_asset_count > 0 || force_compile
        logger.info "#{changed_asset_count} assets have changed. Pre-compiling"
        run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}
      else
        logger.info "#{changed_asset_count} assets have changed. Skipping asset pre-compilation"
      end
    end
  end
于 2012-10-16T18:31:45.040 回答