【问题标题】:Rails 4 ajax:error not triggering unless ajax:success has been triggered firstRails 4 ajax:错误不会触发,除非首先触发 ajax:success
【发布时间】:2014-11-25 05:10:01
【问题描述】:

尝试使用 AJAX 加载 ActiveRecord 验证错误时,我无法弄清楚我做错了什么。除非我已经提交了有效的表单并触发了 ajax:success,否则我无法触发 ajax:error。我尝试只绑定 ajax:error 以查看成功是否会阻止它。我已经阅读了working with javascript in rails 上的 Rails 文档,并在 Google 上搜索了我的问题,但无济于事。我曾尝试同时使用 .bind() 和 .on() 但我没有看到区别。我确信我错过了一些非常简单的东西,但我一直在研究这个太久了,我似乎没有得到任何结果。

这里是代码。

型号

class User < ActiveRecord::Base
  before_create :set_activation_key
  before_save :encrypt_password
  before_save :downcase_username
  after_save :clear_password

  validates :username,
            format: {
                with: /\A.*\z/,
                message: 'invalid'
            },
            uniqueness: {message: 'already in use'},
            presence: {message: 'cannot be blank'}

  validates :email_address,
            format: {
                with: /\A.+@.+\..+\z/,
                message: 'invalid'
            },
            uniqueness: {message: 'already in use'},
            presence: {message: 'cannot be blank'}


  validates :password, :confirmation => true, 
            presence: {message: 'cannot be blank'},
            length: {:within => 6..20,
                     :too_long => 'too long',
                     :too_short => 'too short',
            }

  def encrypt_password
    if password.present?
      self.salt = BCrypt::Engine.generate_salt
      self.password = BCrypt::Engine.hash_secret(password, salt)
    end
  end

  def clear_password
    self.password = nil
  end

  def set_activation_key
    self.activation_key = SecureRandom.urlsafe_base64
  end

  def downcase_username
    self.username = self.username.downcase
  end

  def self.authenticate(username, password)
    user = User.find_by_username(username.to_s.downcase)
    if user && user.password == BCrypt::Engine.hash_secret(password, user.salt)
      user
    else
      nil
    end
  end
end

控制器

class Users::UsersController < ApplicationController

  # GET /register
  def new
    @user = User.new
  end

  # POST /users
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        UserMailer.registration_email(@user.email_address).deliver
        format.html { redirect_to root_path, notice: 'Check your email' }
        format.js
      else
        format.html { render action: 'new' }
        format.js { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  private

  def user_params
    params.require(:user).permit(:username, :email_address, :password, :password_confirmation)
  end
end

部分

<%= form_for User.new, remote: true do |f| %>
    <div id="registration_messages"></div>
    <div id="registration_errors"></div>
    <%= f.label :username %>
    <%= f.text_field :username%>

    <%= f.label :email_address %>
    <%= f.text_field :email_address %>

    <%= f.label :password %>
    <%= f.password_field :password %>

    <%= f.label :password_confirmation, 'Confirm Password' %>
    <%= f.password_field :password_confirmation %>

    <%= f.submit 'Register', :class => 'tiny button' %>
    <a class="close-reveal-modal">&#215;</a>
<% end %>

create.js.erb

$(document).ready(function() {
    $('#new_user')
            .bind("ajax:success", function(event, data, xhr, status){
                var $form = $(this);
                $form.find('input[type=text], input[type=password], textarea').val('');
                $("div#registration_messages").append('<div data-alert class="alert-box success">Check your email</div>');
            }).bind("ajax:error", function(event, data, xhr, error){
                console.log(event);
                console.log(data);
                console.log(xhr);
                console.log(error);
                alert("ajax:error");
            });
});

【问题讨论】:

  • 我对这个品牌的 Rails/Ajax 不太熟悉,但我想知道在您的 respond_to 块的 else 中调用 'render' 是否会阻止它加载部分。尝试删除render json: @user.errors, 看看是否有效。
  • 我怀疑同样的事情,但我还没有找到让它工作的方法。我无法直接删除渲染。我尝试将其删除,但出现其他错误。我现在不在我的开发机器上,所以我不记得昨晚到底发生了什么。我知道简单地删除它并没有产生预期的结果。我将通读this,看看是否能从中找到解决方案。

标签: ruby-on-rails-4 ujs


【解决方案1】:

这对您当前的技术没有帮助,但您可以尝试在纯 JQuery 中执行此操作并放弃 js.erb 文件。一旦你掌握了它,我总是发现这种方式更简单。我希望类似以下代码的内容不会产生您所看到的问题。

控制器

# POST /users
def create
  @user = User.new(user_params)

  respond_to do |format|
    if @user.save
      UserMailer.registration_email(@user.email_address).deliver
      format.html { redirect_to root_path, notice: 'Check your email' }
      format.js { render nothing: true, status: :created }
    else
      format.html { render action: 'new' }
      format.js { render json: @user.errors, status: :unprocessable_entity }
    end
  end
end

javascript.js

  # could go in application.js while you're testing it, but best to factor it out into it's own file.
  $('form#new_user').on('ajax:success', function(event, data, xhr, status) {
    var $form = $(this);
    $form.find('input[type=text], input[type=password], textarea').val('');
    $("div#registration_messages").append('<div data-alert class="alert-box success">Check your email</div>');
  });
  $('form#new_user').on('ajax:error', function(event, data, xhr, status) {
    console.log(event);
    console.log(data);
    console.log(xhr);
    console.log(error);
    alert("ajax:error");
  });

【讨论】:

  • 什么是“另一种方式”?你把它放在 application.js 文件中了吗?
  • 我不会把它放在 application.js 中,但可以放在其他一些 javascript 文件中。我发现这种方式比 Rails 方式更常见。
  • 这绝对有效!我仍然不太明白为什么 rails 方式不起作用。我玩过{ render json: @user.errors ...},这当然是问题的一部分。我现在打算使用这个解决方案,但我很想知道为什么 rails 版本不适合我。
  • 我现在更加确定,通过在您的响应块中调用 render 您将覆盖 Rails 默认渲染操作,该操作会渲染相应的 js.erb 模板。在此处查看接受的答案:stackoverflow.com/questions/9735866/…
  • 没问题!看起来您也可以明确告诉 format.js 呈现 js.erb 模板。在此处查看答案:stackoverflow.com/questions/5350890/…。这也可以让你传递你的状态,比如render "path/to/create.js.erb", status: 422
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多