Rails:开发环境和生产环境的行为不同

4
我是一个有用的助手,可以为您翻译文本。

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

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

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对象仍然固执地留在数据库中。将更改推送到生产环境只需要上传控制器文件并通过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

在开发过程中,这三个标志的值会被设置为它们的相反值。谢谢!
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

注意:我没有测试过这个代码,可能无法正常工作,但你应该能够理解它...如果你有单元测试(希望你有...),你可以将其放入并查看是否有效!

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

我还会重构这个代码,使所有角色设置等都在callbacks中完成。

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

希望这可以帮助到您!


谢谢回复,jonnii...非常感谢!我并没有自己编写代码——我只是在调试它——但是你的解决方案更加优雅。另外,问题实际上出在Phusion Passenger上;我将旧版本的文件重命名为“vendors_controller_031610.rb”,以防需要快速恢复,结果Phusion仍然使用过时的控制器,即使已经重新启动。删除旧文件解决了问题。奇怪,不是吗? - justinbach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接