Rails 4 - 使用update.js.erb部分呈现,不显示更新的值

时间:2014-06-09 22:14:21

标签: ruby-on-rails ajax

在我的Rails应用程序的帐户设置页面上,我尝试使用Ajax在提交更新表单后更新显示的用户设置信息。现在,当我提交表单时,数据库会更新,并且_account_settings.html.erb部分似乎会重新呈现,但部分不会显示更新的信息。例如,假设用户名是“John Doe”,他单击“#edit_name”链接。这将呈现_name_form.html.erb,他可以使用它来更改自己的名字。当他改变他的名字并提交表格时,假设他将其改为“Joe Blow”,表格消失并且名称:<%= current_user.name%> - 点击编辑'再次显示,但名称仍然是“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

1 个答案:

答案 0 :(得分:1)

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

例如:

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