在 Heroku 上预编译资产时如何普遍跳过数据库操作
我正在将 Rails 3.1 应用程序部署到 Heroku 的 Cedar 堆栈。使用 Heroku Cedar 和 Rails 3.1,您可以在本地自己编译资产,让 Heroku 在您推送时编译它们(在“slug”期间)编译”),或者在应用程序运行时即时编译它们。我想做中间选项,让 Heroku 预编译资产。
当 Heroku 运行 asset:precompile 任务时,会出现错误 “无法连接到服务器”,因为应用程序正在尝试连接到数据库,但在 slug 编译的该阶段没有可用的数据库。此时缺少数据库连接是预料之中且不可避免的。我正在寻找一种方法来克服它,因为数据库连接对于资产预编译并不重要。
我的应用程序中尝试连接到数据库的部分是 Devise。 routes.rb 中有一个 devise_for :users
行想要查看 User 模型。
我可以编写一个 rake 任务来删除 devise_for 并将其作为 asset:precompile 的先决条件。我认为这可以解决我的问题,但是我正在寻找一种更通用的解决方案,我可以在 Heroku 上出现此问题的任何 Rails 3.1 应用程序上使用它。
有没有什么东西,或者您能想到什么东西可以消除数据库连接错误,同时仍然运行应用程序足以生成路线和资产路径?
显然,如果应用程序需要在启动期间读取/写入数据,我们无法对其进行存根,但是我们可以自动伪造每个 ActiveRecord 模型吗?
I'm deploying a Rails 3.1 app to Heroku's Cedar stack. With Heroku Cedar and Rails 3.1, you can compile the assets yourself locally, let Heroku compile them when you push (during "slug compilation"), or have them be compiled just-in-time while the app is running. I want to do the middle option, letting Heroku precompile the assets.
When Heroku runs the assets:precompile task, it errors with "could not connect to server" because the app is trying to connect to the database but no database is available at that stage of slug compilation. The lack of database connection is expected and unavoidable at this point. I'm looking for a way to move past it, because a database connection isn't crucial to asset precompilation.
The part of my app that's trying to connect to the database is Devise. There's a devise_for :users
line in routes.rb that wants to look at the User model.
I could just write a rake task that stubs out devise_for and make it a prereq of assets:precompile. I think that would solve my problem, but I'm looking for a more universal solution that I could use on any Rails 3.1 app with this problem on Heroku.
Is there anything out there, or can you conceive of anything that silences database connection errors while still running the app enough to have route and asset path generation?
Obviously if an app needs to read/write data during startup, we can't stub that, but can we fake every ActiveRecord model automatically?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
将其添加到 config/application.rb
花了我一段时间才找到它...将其添加到 config/environments/*.rb 不起作用
更新:它不适用于 Rails 4
add this to config/application.rb
took me a while to hunt this down... adding it to config/environments/*.rb did NOT work
UPDATE: It doesn't work with rails 4
Heroku 现在提供了一个 labs 标志,这将使运行时环境在编译期间可用,这意味着您的应用将能够成功连接到您的
DATABASE_URL
数据库。首先,您需要安装 labs 插件:
然后启用
user-env-compile
实验室功能:Heroku now makes a labs flag available that'll make the runtime environment available during compilation time, which means your app will be able to successfully connect to your
DATABASE_URL
database.First you need to install the labs plugin:
then enable the
user-env-compile
labs feature:对我来说,问题是 activerecord 在
lib/active_record/railtie.rb:92
中调用instantiate_observer
。这将加载观察者和相应的模型。has_and_belongs_to_many
然后连接到数据库。我想当
ENV["RAILS_ASSETS_PRECOMPILE"]
存在时我会重写此方法,该方法由 Bradley 链接到的修复程序中的 devise 使用。编辑:所以这个片段为我修复了它:
For me the problem is activerecord calling
instantiate_observer
inlib/active_record/railtie.rb:92
. This will load the observers and the respective models.has_and_belongs_to_many
then connects to the db.I think I'll override this method when
ENV["RAILS_ASSETS_PRECOMPILE"]
is present, which is used by devise in the fix Bradley linked to.EDIT: So this snippet fixed it for me:
Rails(4.2 Edge)的解决方法:
将以下内容添加为
/config/initializers/precompile.rb
:并在
routes.rb
中使用它,如下所示:Workaround for Rails (4.2 edge):
Add the following as
/config/initializers/precompile.rb
:and use it in your
routes.rb
like this:编辑:这个答案已经过时,不再有效 - 请参阅 fringd 的答案。
不完全是通用存根,但设计现在添加了一个检查来解决这个特定问题。请参阅问题和修复 在 Github 上。通过提供 RAILS_ASSETS_PRECOMPILE 环境配置设备应该跳过构建路由
EDIT: This answer is out of date and no longer works - See fringd's answer.
Not quite a universal stubbing but devise has added a check now to fix this particular problem . See the issue and fix on Github. By providing a RAILS_ASSETS_PRECOMPILE environment config devise should skip building the routes
我将其放在“lib/tasks/assets.rake”中,并且能够获得资产:预编译真正成功。只要您不因需要您的环境而实际访问数据库,这应该就可以工作。它显然对 ActiveRecord 没有帮助,但它应该适用于所有基于 mongoid 的应用程序。
I stuck this in 'lib/tasks/assets.rake' and was able to get assets:precompile to actually succeed. This should work as long as you don't actually access the database as a result of requiring your environment. It obviously won't help with ActiveRecord, but it should work for all mongoid-based apps.
Heroku 添加了一个非官方标志,以使环境(即数据库)在预编译期间可访问。只需要求他们将其打开,资产预编译期间的数据库依赖性就不再是问题。不确定该标志是否/何时正式可用,或者它是否只是新的默认值。
Heroku added an unofficial flag to make the environment (i.e. also the DB) accessible during precompilation. Just ask them to switch it on and DB dependencies during asset precompilations are no longer an issue. Not sure, if/when this flag is officially available though, or if it will simply be the new default.
Spork.trap_method也是一个有趣的解决方案,解决了Devise的routes_for在加载过程早期调用模型的问题。 AFAIK 解决方案不能直接应用,但它正在解决同一类型的问题,因此它可能会为某人提供灵感。
Spork.trap_method
Spork.trap_method is also an interesting solution to the problem of Devise's routes_for calling the model early in the load process. Solution can't be applied directly AFAIK, but it's solving the same sort of problem, so it might provide inspiration for somebody.
Spork.trap_method
我缺乏足够的声誉来发表评论,所以这是另一个答案。
确实,@fringd 的顶级答案在 Rails 4 上不起作用。但是,我发现这种技术可以工作:
https://iprog.com/posting/2013/07/errors-when-precompiling-assets-in-rails-4-0
尽管如此,我重新排列了 BASH 变量,如下所示:
顺便说一句如果您需要构建 Docker 映像,这是一个极好的帮助。将该行放入您的 Dockerfile 中,以便您的数据库可以驻留在不同的容器中,并且您的应用程序容器不需要在每次启动时预编译资产!
I lack sufficient reputation to comment, so here's another answer.
It's true that @fringd's top-rated answer does not work on Rails 4. I have, however, found this technique to work:
https://iprog.com/posting/2013/07/errors-when-precompiling-assets-in-rails-4-0
Although, I rearranged the BASH variables like so:
BTW, This is a fantastic aid if you need to build a Docker image. Put that line into your Dockerfile so your DB can live in a different container and your app containers don't need to precompile assets every time they start up!
禁用增强现实:
Disable AR: