4

Phusion Passengerを使用してデプロイされた Rails サイトで保守作業を行っています。ワークフローは、Railsian の標準的な 3 層のテスト - 開発 - 生産の配置とは少し異なります。代わりに、並列の Oracle データベースに対して実行される同じコードベースの 2 つの別個のインストールがあります。開発サイトは qa.domain.com にあり、ライブ サイトは www.domain.com にあります。

次のコード スニペット (AuthenticatedSystem を使用する「vendors_controller.rb」から) で、2 つの環境間で異なる動作が発生しています。

def create
  @user = current_user || User.new(params[:user])
  @registration = Registration.new(params[:registration])

  unless current_user

    @user.user_type = 'vendor'
    @user.active = 1

    if @user.save
      @user.activate!
      @user.has_role 'owner', @user
      @user.has_role 'vendor'
      self.current_user = user = @user

      @registration.active = 1
      @registration.email = @user.email
      @registration.user_id = @user.id
      if @registration.save
        send_confirmation(@user)
        send_solicitations_notifications(@registration) if @registration.notification_desired == true
        redirect_to thank_you_vendors_path
      else
        # THIS BEHAVIOR DIFFERS ACROSS PRODUCTION AND DEVELOPMENT
        @user.destroy
        self.current_user = user = nil
        # END DIFFERENCE
        respond_to do |format|
          format.html { render :action => 'new' }
          format.xml  { render :xml => @registration.errors, :status => :unprocessable_entity }
        end
      end

    else
      respond_to do |format|
        format.html  { render :action => 'new' }
        format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
      end
    end
...

コメント間のコードは、システムが対応する登録を作成できなかった場合、作成されたばかりのユーザー オブジェクトを破棄します。開発サーバーでは問題なく動作しますが、登録の保存に失敗した場合でも User オブジェクトが頑固にデータベースにぶら下がっている運用サーバーでは機能しません。変更を本番環境にプッシュするのは、コントローラ ファイルをアップロードしtouch tmp/restart.txtてシェル経由で行うだけです。それ以外の点では、2 つのコードベースは同一です。この違いの原因は何ですか?

ご検討いただきありがとうございます。

ジャスティン

production.rb編集:問題の診断に役立つ可能性のある 2 つのインストールにいくつかの違いがあります。制作にあたって、

config.cache_classes = true

# Full error reports are disabled and caching is turned on
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching             = true

開発中、これらの 3 つのフラグは逆の値に設定されます。ありがとう!

4

1 に答える 1

1

コードについて変更することを検討する必要があることがいくつかあります。

  1. トランザクションを使用していません
  2. あなたはコントローラーでやりすぎです

あなたが問題を抱えている理由はおそらく本番環境と開発環境の違いによるものだと言っていますが、おそらくこれは次のとおりです。

config.cache_classes = false

ただし、すべてのアクションが遅くなるため、本番環境でこれを変更する必要はないと思います。代わりに、実稼働環境に厳密に一致するステージング環境を用意することをお勧めします。

あなたの問題を解決するために、私はおそらく次のようにアクションを書き直します:

# using before filters will keep your actions tight
before_filter :cannot_create_user, :if => :signed_in?

def create
  # setup all the objects
  @user = User.new(params[:user])

  @user.user_type = 'vendor'
  @user.active = 1

  @user.has_role 'owner', @user
  @user.has_role 'vendor'

  @registration = @user.registrations.build(params[:registration])
  @registration.active = 1
  @registration.email = @user.email

  # make sure everything is valid before trying to save and activate
  if @user.valid?
    @user.save!  # might not need this if activate calls save!
    @user.activate!

    # this should probably be a sign_in() method... 
    self.current_user = @user

    send_confirmation(@user)
    send_solicitations_notifications(@registration) if @registration.notification_desired?

    redirect_to thank_you_vendors_path
  else
    respond_to do |format|
      format.html { render :action => 'new' }
      format.xml  { render :xml => @registration.errors, :status => :unprocessable_entity }
    end
  end

...
end


protected 

def signed_in?
  !current_user.nil?
end

def cannot_create_user
  respond_to do |format|
    format.html  { render :action => 'new' }
    format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
  end
end

nb私はこれをテストしませんでした、それは機能しないかもしれませんが、あなたはアイデアを得る必要があります...あなたがユニットテストを持っているなら(私はあなたがそうすることを願っています...)あなたはそれをドロップしてそれが機能するかどうか見ることができるはずです!!

次のステップは、登録オブジェクトにuseaccepts_nested_attribute_forを使用して、ユーザーパラメーターの一部として送信できるようにすることです。

また、これをリファクタリングして、すべての役割設定などがコールバックで行われるようにします。

この時点で、createアクションは非常に単純である可能性が高く、継承されたリソースを使用するようにコントローラーを切り替えることができます。

これがお役に立てば幸いです。

于 2010-03-16T15:02:55.610 に答える