【问题标题】:Rails 4 - partial rendered with update.js.erb not showing updated valuesRails 4 - update.js.erb 部分渲染不显示更新的值
【发布时间】:2014-06-09 22:14:20
【问题描述】:

在我的 Rails 应用程序的帐户设置页面上,我尝试使用 Ajax 在提交更新表单后更新显示的用户设置信息。现在,当我提交表单时,数据库会更新,并且 _account_settings.html.erb 部分似乎会重新呈现,但部分不会显示更新的信息。例如,假设用户名为“John Doe”,他单击了“#edit_name”链接。这会呈现 _name_form.html.erb,他可以使用它来更改他的名字。当他更改姓名并提交表单时,假设他将其更改为“Joe Blow”,表单消失并且“名称: - click to edit”再次出现,但名称仍然“John Doe”即使数据库中的名称现在是“Joe Blow”。如果我刷新页面,名称现在显示为“Joe Blow”。我正在使用设计并制作了一个自定义注册控制器,以允许用户在不输入密码的情况下更新某些属性(名称仍然需要当前密码)。我使用了this code provided by the devise 并简单地添加了

respond_to do |format|
    format.html { redirect_to edit_user_registration_path }
    format.js
end

到上述链接中“if @user.update_attributes(account_update_params)”块的末尾。关于为什么重新渲染的部分没有显示更新的用户信息的任何想法?

edit.html.erb
<h1>Account Settings</h1>
<div id="account_settings_container">
    <%= render 'account_settings' %>
</div>


_account_settings.html.erb
<div class="user-attribute-container">
    <%= link_to "#", class: "edit-attribute", id: "edit_name", remote: true do %>
        <p>Name: <%= current_user.name %> - click to edit</p>
    <% end %>
</div>

<div class="user-attribute-container">
    <%= link_to "#", class: "edit-attribute", id: "edit_email", remote: true do %>
        <p>Email: <%= current_user.email %> - click to edit</p>
    <% end %>
</div>

<div class="user-attribute-container">
    <%= link_to "#", class: "edit-attribute", id: "edit_password", remote: true do %>
        <p>Password: click to edit your password</p>
    <% end %>
</div>

<%= javascript_tag do %>
    $("#edit_name").click(function() {
        $(this).hide().after("<%= escape_javascript(render('name_form')) %>");
    });
    $("#edit_email").click(function() {
        $(this).hide().after("<%= escape_javascript(render('email_form')) %>");
    });
    $("#edit_password").click(function() {
        $(this).hide().after("<%= escape_javascript(render('password_form')) %>");
    });
<% end %>


_name_form.html.erb (the email and password form partials have :email, :password & :password_confirmation instead of :name, otherwise they're the same)
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :method => :put, :html => { id: "edit_user_name" }, remote: true) do |f| %>
    <%= f.label :name, "Name" %>
    <%= f.text_field :name %>

    <%= f.label :password_field, "Password" %>
    <%= f.password_field :current_password %>

    <%= f.submit "Update" %>
<% end %>


update.js.erb
$("#account_settings_container").html("<%= escape_javascript(render('account_settings')) %>");

来自日志文件:

Started PUT "/users" for 127.0.0.1 at 2014-06-09 15:01:21 -0700<br>
Processing by RegistrationsController#update as JS<br>
  Parameters: {"utf8"=>"✓", "user"=>{"name"=>"Joe Blow", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}<br>
  [1m[36mUser Load (0.0ms)[0m  [1mSELECT "users".* FROM "users" WHERE "users"."id" = 14 ORDER BY "users"."id" ASC LIMIT 1[0m<br>
  [1m[35mUser Load (0.0ms)[0m  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 14]]<br>
  [1m[36m (0.0ms)[0m  [1mBEGIN[0m<br>
  [1m[35mSQL (0.0ms)[0m  UPDATE "users" SET "name" = $1, "updated_at" = $2 WHERE "users"."id" = 14  [["name", "Joe Blow"], ["updated_at", Mon, 09 Jun 2014 15:01:21 PDT -07:00]]<br>
  [1m[36m (0.0ms)[0m  [1mCOMMIT[0m<br>
  Rendered registrations/_name_form.html.erb (15.6ms)<br>
  Rendered registrations/_email_form.html.erb (0.0ms)<br>
  Rendered registrations/_password_form.html.erb (15.6ms)<br>
  Rendered registrations/_account_settings.html.erb (46.9ms)<br>
  Rendered registrations/update.js.erb (46.9ms)<br>
Completed 200 OK in 219ms (Views: 78.1ms | ActiveRecord: 0.0ms)

自定义设计注册控制器:

class RegistrationsController < Devise::RegistrationsController

    def update
        @user = User.find(current_user.id)

        successfully_updated = if needs_password?(@user, params)
          @user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
        else
            # remove the virtual current_password attribute
            # update_without_password doesn't know how to ignore it
            params[:user].delete(:current_password)
            @user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
        end

        if successfully_updated
            # sign_in @user, :bypass => true
            respond_to do |format|
                format.html { redirect_to edit_user_registration_path }
                format.js
            end
        else
            respond_to do |format|
                format.html { render "edit" }
                format.js
            end
        end
    end

    private

    def needs_password?(user, params)
        user.email != params[:user][:email] || params[:user][:password].present? || user.name != params[:user][:name] 
    end
 end

【问题讨论】:

  • 我会自己尝试@user.update_attributes(account_update_params),然后你的 if 块可能是if @user.save ...。我认为正在发生的事情是您的更改正在保存到数据库中,但直到方法完成执行后才保存,其中包括部分的重新渲染。
  • registrations/update.js.erb 是什么样的?
  • 这似乎没有解决它。我注意到的一件事是,单击更新后 _account_settings.html.erb 的 &lt;p&gt;Name: &lt;%= current_user.name %&gt; - click to edit&lt;/p&gt; 部分具有旧名称,但来自同一部分中的 javascript 标记的名称输入标记的值具有更新的名称。
  • @Swards - $("#account_settings_container").html("&lt;%= escape_javascript(render('account_settings')) %&gt;");
  • @sc_12_19 你能从你的 update.js.erb 文件中发出警报吗?

标签: ruby-on-rails ajax


【解决方案1】:

current_user 由 Devise 使用 before_filter 生成。因此,返回的对象将是调用该操作方法之前的用户。您需要使用 @user 对象,它是由 action 方法修改的用户对象。

例如:

<p>Name: <%= @user.name %> - click to edit</p>

【讨论】:

  • 解决了!谢谢!
猜你喜欢
  • 2017-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 2011-12-17
  • 1970-01-01
  • 2016-11-12
  • 1970-01-01
相关资源
最近更新 更多