2

私はコントローラからPDFを生成するためにエビを使用しています.URLに直接アクセスすると、問題なく動作します.IE localhost:3000/responses/1.pdf

しかし、メーラーに含めるためにこのファイルをオンザフライで生成しようとすると、すべてがフリーズしてタイムアウトになります。

ファイルを生成/添付するためのさまざまな方法を試しましたが、結果が変わったものはありません。

また、Net::HTTP のタイムアウトを無駄に変更しようとしましたが、タイムアウトするのに時間がかかります。

Rails コンソールでこのコマンドを実行すると、PDF データ ストリームを受け取ります。

Net::HTTP.get('127.0.0.1',"/responses/1.pdf", 3000)

しかし、このコードをコントローラーに含めると、タイムアウトになります。

2 つの異なる方法を試しましたが、どちらも繰り返し失敗します。

方法 1 コントローラー:

http = Net::HTTP.new('localhost', 3000)
http.read_timeout = 6000
file = http.get(response_path(@response, :format => 'pdf')) #timeout here
ResponseMailer.confirmComplete(@response,file).deliver #deliver the mail!

方法 1 メーラー:

def confirmComplete(response,file)
  email_address = response.supervisor_id
  attachments["test.pdf"] = {:mime_type => "application/pdf", :content=> file}
  mail to: email_address, subject: 'Thank you for your feedback!'
end

上記のコードはタイムアウトします。

方法 2 コントローラー:

ResponseMailer.confirmComplete(@response).deliver #deliver the mail!

方法 2 メーラー:

def confirmComplete(response)
email_address = response.supervisor_id
attachment "application/pdf" do |a|
    a.body = Net::HTTP.get('127.0.0.1',"/responses/1.pdf", 3000) #timeout here
    a.filename = "test.pdf" 
end
mail to: email_address, subject: 'Thank you for your feedback!'

終わり

a.body と a.filename を切り替えると、最初にエラーが発生します

undefined method `filename=' for #<Mail::Part:0x007ff620e05678>

私が見つけたすべての例には、異なる構文または提案がありますが、Net::HTTP タイムアウトの問題を解決するものはありません。レール 3.1、ルビー 1.9.2

4

2 に答える 2

2

問題は、開発中、実行しているサーバープロセスが1つだけであり、電子メールの生成でビジー状態になっていることです。そのプロセスは、PDFを生成するための別の要求を(それ自体に)送信し、応答を待機しています。PDFのリクエストは、基本的にサーバーでPDFを取得できるように並んでいますが、サーバーは電子メールの生成に忙しく、終了する前にPDFを取得するのを待っています。したがって、あなたは永遠に待っています。

あなたがする必要があるのは、2番目のサーバープロセスを起動することです...

script/rails server -p 3001

次に、次のようなPDFを取得します...

args = ['127.0.0.1','/responses/1.pdf']
args << 3001 unless Rails.env == 'production'
file = Net::HTTP.get(*args)

余談ですが、実稼働マシンで実行しているサーバーによっては、127.0.0.1を指すときに問題が発生する可能性があります。本番環境では、これを動的にして完全なドメインを指す必要があるかもしれませんが、それは簡単なはずです。

于 2011-12-14T21:30:44.483 に答える
1

https://stackoverflow.com/users/811172/jon-garvinの分析に同意しますが、1 つのサーバー プロセスしか実行していませんが、別の解決策について言及します。コントローラーに依存しないように、PDF 生成をリファクタリングします。

Prawntoを使用している場合、次のようなビューがあると思います

# app/views/response.pdf.prawn
pdf.text "Hello world"

これをモデルに移動しますResponse: (または、プレゼンターなど、より適切な場所)

# app/models/response.rb
require 'tmpdir'
class Response < ActiveRecord::Base
  def pdf_path
    return @pdf_path if @pdf_generated == true
    @pdf_path = File.join(Dir.tmpdir, rand(1e11).to_s)
    Prawn::Document.generate(@pdf_path) do |pdf|
      pdf.text "Hello world"
    end
    @pdf_generated = true
    @pdf_path
  end

  def pdf_cleanup
    if @pdf_generated and File.exist?(@pdf_path.to_s)
      File.unlink @pdf_path
    end
  end
end

次に、あなたResponsesControllerができること:

# app/controllers/responses_controller.rb
def show
  @response = Response.find params[:id]
  respond_to do |format|
    # this sends the PDF to the browser (doesn't email it)
    format.pdf { send_file @response.pdf_path, :type => 'application/pdf', :disposition => 'attachment', :filename => 'test.pdf' }
  end
end

メーラーで次のことができます。

# this sends an email with the PDF attached
def confirm_complete(response)
  email_address = response.supervisor_id
  attachments['test.pdf'] = {:mime_type => "application/pdf", :content => File.read(response.pdf_path, :binmode => true) }
  mail to: email_address, subject: 'Thank you for your feedback!'
end

tmpdir に作成したため、サーバーの再起動時に自動的に削除されます。クリーンアップ関数を呼び出すこともできます。

最後に 1 つ: 別のモデル名などを使用するSupervisorReportことResponseをお勧めします。後で名前空間の問題が発生する可能性があります)。

于 2011-12-14T23:20:19.000 に答える