为什么x = params.dup无效但x = @ model.dup工作?

时间:2011-11-17 00:05:09

标签: ruby-on-rails ruby-on-rails-3

这是我正在做的事情:

  1. 更新记录并存储其原始值
  2. 稍后将记录的值与原始值进行比较,以查看已更改的内容
  3. 在一段纯文本中标记这些更改
  4. 然而,我在#1

    遇到了意想不到的事情
    def update
      @hardware = Hardware.find(params[:id])
      old_hardware = @hardware
      old_hardware_status_id = @hardware.status_id
    
      test_text = "#{old_hardware[:status_id]} - BV #{old_hardware_status_id} - BSUB #{params[:hardware][:status_id]}"
    
      respond_to do |format|
        if @hardware.update_attributes(params[:hardware])
          test_text = "#{test_text}<p>#{old_hardware[:status_id]} - AV #{old_hardware_status_id} - ASUB #{params[:hardware][:status_id]}"
    
          format.html { 
            render :text => test_text
            #redirect_to(@hardware, :notice => "Hardware was successfully updated.") 
          }
          format.xml  { head :ok }
        else
          format.html { render :action => "edit" }
          format.xml  { render :xml => @hardware.errors, :status => :unprocessable_entity }
        end
      end
    end
    

    提供以下输出:

    5 - BV 5 - BSUB 10
    10 - AV 5 - ASUB 10 
    

    人们会期望它是:

    5 - BV 5 - BSUB 10
    5 - AV 5 - ASBU 10
    

    当params或params的子集用作新变量的值时,新变量只是引用与params相同的确切地址/值而不是创建值的新实例。如果您在update_attributes行之前执行duplicate_params = params.dup之类的操作,则会出现同样的情况,然后输出duplicate_params的不同属性...

    def update
      @hardware = Hardware.find(params[:id])
      old_params = params[:hardware].dup
      old_hardware_status_id = @hardware.status_id
    
      test_text = "#{old_params[:status_id]} - BV #{old_hardware_status_id} - BSUB #{params[:hardware][:status_id]}"
    
      respond_to do |format|
        if @hardware.update_attributes(params[:hardware])
          test_text = "#{test_text}<p>#{old_params[:status_id]} - AV #{old_hardware_status_id} - ASUB #{params[:hardware][:status_id]}"
    
          format.html { 
            render :text => test_text
            #redirect_to(@hardware, :notice => "Hardware was successfully updated.") 
          }
          format.xml  { head :ok }
        else
          format.html { render :action => "edit" }
          format.xml  { render :xml => @hardware.errors, :status => :unprocessable_entity }
        end
      end
    end
    

    提供以下输出:

    5 - BV 5 - BSUB 10
    10 - AV 5 - ASUB 10 
    

    人们会期望它是:

    5 - BV 5 - BSUB 10
    5 - AV 5 - ASBU 10
    

    换句话说,一旦update_attributes运行,任何基于原始参数的值(例如old_hardware或duplicate_params)都会更新。

    但是,如果在原始实例中你执行的操作不会发生:old_hardware = @ hardware.dup,它会给你:

    5 - BV 5 - BSUB 10
    5 - AV 5 - ASBU 10
    

    问题:

    1. 为什么“duplicate_params = params.dup”在“old_hardware = @ hardware.dup”工作时不起作用?
    2. 这是不典型的情况吗?我只是在复制params和@models时才遇到这个问题,而且它似乎与我的其他RoR体验不一致。

1 个答案:

答案 0 :(得分:0)

在更新之前插入字符串,更改值,然后将带有先前插值的旧字符串添加到包含新值的字符串的前面。

这就是我期望发生的事情 - 更新后第一个字符串中的旧值不会被重新插值。

编辑重复地图工作正常:

> foo = { hardware: { id: 10, foo: "bar" } }
=> {:hardware=>{:id=>10, :foo=>"bar"}}

> old = foo[:hardware].dup
=> {:id=>10, :foo=>"bar"}

> foo[:hardware]
=> {:id=>10, :foo=>"bar"}

> foo[:hardware][:foo] = "baz"
=> "baz"

> foo[:hardware]
=> {:id=>10, :foo=>"baz"}

> old
=> {:id=>10, :foo=>"bar"}