【问题标题】:How to access the updated object in a javascript callback (instead of the old object)如何在 javascript 回调中访问更新的对象(而不是旧对象)
【发布时间】:2015-01-14 18:43:54
【问题描述】:

基于here 提供的有用且有效的解决方案,我也在尝试修复我的更新回调。

问题是,我试图从中提取数据的特定 unit 始终是旧的缓存版本,即使此回调是由成功的 update 操作触发的。

// callback triggered by the update action

$('.best_in_place').bind("ajax:success", function () {
   ...
    console.log(unit.duration);
    // which is exactly the same as
    console.log(<%= Unit.find(unit.id).unit_users.pluck(:duration).sum %>);
    // and both print the OLD duration val instead of the updated val which is in the database
});

还有 unit_users_controller 代码...

  def update
    @unit = @unituser.unit

    respond_to do |format|
      if @unituser.update(unit_user_params)
        @unit.reload
        logger.info('-----------------------------------------------------------------')
        logger.info('@unit.duration in the controller is ' + @unit.duration.to_s) # which is the correct value
        logger.info('-----------------------------------------------------------------')
        gon.unit_duration = @unit.duration # an experiment which didn't work for me
        format.json {respond_with_bip(@unituser) }
      else
        # format.html { render :action => 'edit' }
        format.json { respond_with_bip(@unituser) }
      end
    end
  end

我尝试了多个版本的unit.reload,但没有任何帮助。可能是我放错地方了?

【问题讨论】:

  • 能贴出控制器代码吗?
  • @RodrigoZurek 与控制器代码无关。控制器与此无关。这是关于对 .js.erb 文件如何工作的误解。
  • 它与控制器有关,如果您想要更新的对象,它必须通过控制器并且您必须以某种方式将其取回
  • @RodrigoZurek 正确的解决方案是,是的。显示控制器代码无关紧要,因为控制器代码不是问题。问题是在视图中滥用&lt;%= %&gt;
  • 粘贴在我的控制器代码中...

标签: ruby-on-rails best-in-place


【解决方案1】:

我前段时间做过这个,这是我的代码,也许它会对你有所帮助:

Javascript:

$(document).ready(function() {
  $('.price_bind').bind("ajax:success", function (event, data, status, xhr) {
      var parsed_data = jQuery.parseJSON(data);
      $(this).text(parsed_data.newprice);
      $(this).parentsUntil('body').find(".totalpricep span").text(parsed_data.totalprice);
  });
}

查看:

<%= best_in_place detail, :price, :classes => 'price_bind', :path => purchase_detail_path(@purchase, detail)%>

控制器:

 def update
    respond_to do |format|
      if @detail.update_attributes(params[:detail])
        @n=@detail.mk_bal
        @r=false
        if @detail.purchase != nil
          @p=@detail.purchase.totalprice
        if params[:detail]['status'] && @purchase.step==1
          @remdet = @purchase.details.where(:step => 1, :status => false)
          if @remdet.empty?
            @purchase.update_attribute(:step, 2)
            @r=true
          end  
        end
        else
          @p=nil
        end
        format.html { redirect_to @detail, notice: 'Detail was successfully updated.' }
        format.json { render :json => {:newprice => @n, :totalprice => @p, :newstatus => @detail.status, :refresh => @r}}
      else
        format.html { render action: "edit" }
        format.json { render json: @detail.errors, status: :unprocessable_entity }
      end
    end
  end

【讨论】:

  • 但您的 format.json 中没有 {respond_with_bip(@unituser) },如果您希望更新该字段,我认为这是强制性的。 ??
  • 对象在此处响应之前正在更新:@detail.update_attributes(params[:detail]),或您想要的任何其他更新。之后,您可以根据需要从控制器响应,在这种情况下,它需要 JSON 响应,您可以返回所需的新对象的任何方面
  • so format.json { render :json => {:unit_duration => @unit.duration.to_s }} 确实得到了我需要的数据,但是我的 best_in_place 字段现在显示了错误的数据。有什么办法可以将上面的渲染与之前的 format.json {respond_with_bip(@unituser) } 结合起来,让我两全其美?
  • 这是我回答中的 javascript 部分,一旦请求成功,您将替换从控制器获得的值,并在视图上替换它。 $(this).parentsUntil('body').find(".totalpricep span").text(parsed_data.totalprice);
  • 好的 - 我想我明白了。您忽略了 respond_with_bip 帮助器并自己重建了它的功能。谢谢!
【解决方案2】:

这与缓存无关。您的 Ruby 代码在 服务器 端进行评估,在 JavaScript 发送到客户端之前,它只评估一次,远在 AJAX 请求发生之前。

客户端永远不会看到这一行:

console.log(<%= Unit.find(unit.id).unit_users.pluck(:duration).sum %>);

客户看到的都是这样的:

console.log(32); // or whatever the sum is

您不能在此处使用&lt;%= %&gt;。那将始终为您提供原始价值。相反,您需要将新值发送给客户端以响应 AJAX 请求。

【讨论】:

  • 糟糕——Unit.find 是深夜的愚蠢行为。现在更清楚了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多