【问题标题】:Rails: Different behavior on dev and productionRails:开发和生产的不同行为
【发布时间】:2010-03-16 13:39:57
【问题描述】:

我正在使用Phusion Passenger 部署的 Rails 站点进行维护工作。工作流程与标准的三层 Railsian 测试-开发-生产安排略有不同;相反,针对并行 Oracle 数据库运行相同代码库的两个单独安装;开发站点位于 qa.domain.com,实时站点位于 www.domain.com

我在两个环境之间的以下代码 sn-p(来自使用 AuthenticatedSystem 的“vendors_controller.rb”)中遇到了不同的行为:

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
...

如果系统无法创建相应的注册,则 cmets 之间的代码会破坏刚刚创建的用户对象。它在开发服务器上运行良好,但在生产服务器上却不行,即使保存注册失败,用户对象也会顽固地挂在数据库周围。将更改推送到生产环境很简单,只需上传控制器文件并通过 shell 执行touch tmp/restart.txt。这两个代码库在其他方面是相同的;什么可能导致这种差异?

感谢您的考虑!

贾斯汀

编辑:production.rb 在两个安装中存在一些差异,这可能有助于诊断问题。在生产中,

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

在开发过程中,这三个标志被设置为它们的相反值。谢谢!

【问题讨论】:

    标签: ruby-on-rails development-environment production-environment


    【解决方案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
    

    n.b.我没有对此进行测试,它可能不起作用,但你应该明白......如果你有单元测试(我希望你这样做......)你应该能够将它放入并查看它是否有效!

    您的下一步是使用 accepts_nested_attribute_for 作为您的注册对象,以便它可以作为用户参数的一部分提交。

    我还会重构它,以便所有角色设置等...都在 callbacks 中完成。

    此时您的create 操作很可能非常简单,您可以将控制器切换为使用inherited resources。

    我希望这会有所帮助!

    【讨论】:

    • 感谢您的回复,jonnii...非常感谢!我自己没有编写代码——我只是在调试它——但你的解决方案要优雅得多。此外,事实证明问题出在 Phusion Passenger 上。我将文件的旧版本重命名为“vendors_controller_031610.rb”,以防我需要快速恢复,结果发现 Phusion 使用的是过时的控制器,即使在重新启动后也是如此。删除旧文件解决了这个问题。奇怪吧?
    猜你喜欢
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 2019-06-28
    • 1970-01-01
    相关资源
    最近更新 更多