2011-09-15 27 views
31

我正在爲Heroku的Cedar堆棧部署Rails 3.1應用程序。使用Heroku Cedar and Rails 3.1,您可以在本地編譯資產,讓Heroku在推送時(在「slug編譯」期間)編譯它們,或者讓它們在應用程序運行時及時編譯。我想做中間選項,讓Heroku預先編譯資產。如何在Heroku上預編譯資源時普遍跳過數據庫觸摸

當Heroku運行資產:預編譯任務時,由於應用程序試圖連接到數據庫,但在該段塞編譯階段沒有數據庫可用,因此它出錯"could not connect to server"。目前缺乏數據庫連接是不可避免的。我正在尋找一種超越它的方式,因爲數據庫連接對資產預編譯並不重要。

我嘗試連接到數據庫的應用程序的一部分是Devise。 routes.rb中有一個devise_for :users行希望查看用戶模型。

我可以寫一個rake任務,將devise_for存根並將其作爲資源的前置部分:預編譯。我認爲這將解決我的問題,但我正在尋找更通用的解決方案,我可以使用任何 Rails 3.1應用程序與Heroku上的這個問題。

那裏有什麼東西,或者你可以想象任何能夠沉默數據庫連接錯誤的東西,同時仍然運行足夠的應用程序來創建路徑和資產路徑?

顯然,如果應用程序需要在啓動過程中讀取/寫入數據,我們不能存根,但我們是否可以自動僞造每個ActiveRecord模型?

回答

3

編輯:這個答案是過時的,不再適用 - 見fringd的答案。

不是一個普遍存根,但設計現在增加了一個檢查來解決這個特定的問題。請參閱Github上的issuefix。通過提供一個RAILS_ASSETS_PRECOMPILE環境配置設計應該跳過建設路線

+0

真棒!感謝您提醒我。我用Heroku添加了我的票據,如果他們還沒有,他們應該設置這個環境變量。 – jasongarber

+2

對不起,我認爲這個修補程序實際上已經退出了Devise和Rails,Jose Valim做了一些奇特的步法來嘗試解決這個問題,但是我認爲他認爲這不是他們可以做的太多的事情。這個時間點。如果它仍然與Devise HEAD和Rails 3-1穩定的分支一起被破壞,恐怕我認爲除了通過設計模型進行工作以及試圖找出造成問題的具體方法之外,還有什麼可做的。 –

+1

感謝您的更新。 Heroku告訴我他們正在從另一個角度處理這個問題。猜猜我們只需要等待它擺脫。我對自己的情況有一個解決方法。 – jasongarber

1

我在'lib/tasks/assets.rake'中卡住了這個,並且能夠獲取資源:預編譯實際成功。只要您不需要您的環境,實際上不訪問數據庫,這應該工作。它顯然不會幫助ActiveRecord,但它應該適用於所有基於mongoid的應用程序。

task 'assets:precompile' => 'assets:stub_mongoid' 

task 'assets:stub_mongoid' do 
    def Mongoid.load!(*args) 
    true 
    end 
end 
5

對我來說,問題是activerecord調用instantiate_observerlib/active_record/railtie.rb:92。這將加載觀察者和相應的模型。 has_and_belongs_to_many然後連接到數據庫。

我想我會重寫此方法,當ENV["RAILS_ASSETS_PRECOMPILE"]是存在的,這是由設計使用的修復布拉德利鏈接到。

編輯:所以這個片段固定對我來說:

namespace :assets do 
    # Prepend the assets:precompile_prepare task to assets:precompile. 
    task :precompile => :precompile_prepare 

    # This task will be called before assets:precompile to optimize the 
    # compilation, i.e. to prevent any DB calls. 
    task 'precompile_prepare' do 
    # Without this assets:precompile will call itself again with this var set. 
    # This basically speeds things up. 
    ENV['RAILS_GROUPS'] = 'assets' 

    # Devise uses this flag to prevent connecting to the db. 
    ENV['RAILS_ASSETS_PRECOMPILE'] = 'true' 

    # Prevent loading observers which will load the models which in turn may hit 
    # the DB. 
    module ActiveModel::Observing::ClassMethods 
     def instantiate_observers; end 
    end 

    # Prevent route drawing because certain gems might get called which will hit 
    # the DB. 
    class ActionDispatch::Routing::RouteSet 
     def draw; end 
    end 
    end 
end 
+0

謝謝,整個上午都把我的頭髮拉出來解決這個問題! – aaronrussell

+0

也爲我工作的一種享受。謝謝。 – Ivan

0

Spork.trap_method也是一個有趣的解決方案制定的routes_for的問題,在加載過程的早期調用模型。解決方案不能直接應用AFAIK,但它解決了同樣的問題,所以它可能爲某人提供靈感。

Spork.trap_method

46

將此添加到配置/應用程序中。RB

config.assets.initialize_on_precompile=false             

我花了一段追捕下來...添加它來配置/環境/ * RB沒有工作

UPDATE:它不與軌工作4

+1

看來,如果你在你的主SASS文件@import(「指南針」)(讓所有的羅盤混入),這是行不通的。它會導致'文件導入未找到或不可讀:指南針'錯誤。 require'compass'包含在application.rb文件中,但是如果未加載未加載的環境。有誰知道解決這個問題的方法嗎? – Marc

+0

它的工作對我來說,我使用Mongoid與導軌3.1.3 –

+3

這也援引官方的Rails指南,瞭解有關資產管道:http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets –

1

Heroku添加了一個非官方標誌,使預編譯過程中可以訪問環境(即DB)。只要求他們將其打開,資產預編譯期間的數據庫依賴關係不再是問題。不確定,如果/當這個標誌正式可用,或者它只是新的默認值。

+0

謝謝,尼科。我昨天在幫這個朋友,我們確實可以使用它!我認爲這會幫助很多人。乾杯! – jasongarber

+0

你現在可以自己啓用這個標誌。我會發佈一個關於它的答案。 – kch

13

Heroku現在提供了一個labs標誌,可在編譯期間使運行環境變爲可用,這意味着您的應用程序將能夠成功連接到您的DATABASE_URL數據庫。

首先,你需要安裝labs插件:

$ heroku plugins:install http://github.com/heroku/heroku-labs.git 

然後啓用user-env-compile labs feature

$ heroku labs:enable user-env-compile --app your-app-name 
+0

在這個頁面上的所有建議中,這是唯一對我有用的東西。 FYI:Rails 3.2.0.rc2 –

+0

最後,一個工作解決方案。我希望Heroku在他們的Rails疑難解答頁面上記錄這個功能。 – lupefiasco

+0

這就是答案!如果你有任何試圖無條件訪問數據庫的gem(設計?active_admin?等),那麼這是唯一實際工作的解決方案。萬分感謝。 – trisweb

3

解決方法爲Rails(4.2邊):

添加如下/config/initializers/precompile.rb

module Precompile 

    # Public: ignore the following block during rake assets:precompile 
    def self.ignore 

    unless ARGV.any? { |e| e == 'assets:precompile' } 
     yield 
    else 
     line = caller.first 
     puts "Ignoring line '#{line}' during precompile" 
    end 

    end 

end 

,並用它在你的routes.rb這樣的:

Precompile.ignore { ActiveAdmin.routes(self) } 
0

我缺乏足夠的信譽發表評論,所以這裏的另一個答案。

這是真的,@ fringd頂級的答案並不on Rails的4.我有工作,但是,發現這種技術的工作:

https://iprog.com/posting/2013/07/errors-when-precompiling-assets-in-rails-4-0

雖然,我重新安排了BASH變量,就像這樣:

~$ RAILS_ENV=production DATABASE_URL=postgresql://user:[email protected]/dbname bundle exec rake assets:precompile 

順便說一句,如果你需要建立一個Docker映像,這是一個很棒的輔助工具。將該行放入您的Dockerfile中,以便您的數據庫可以位於不同的容器中,並且您的應用容器不需要在每次啓動時預先編譯資源!

+0

沒有爲我工作。 – EightyEight

0

禁用AR:

config = Rails.application.config 
def config.database_configuration 
    {} 
end 

ar = ActiveRecord::Base 
def ar.establish_connection 
end 
相關問題