如何在rails中显示Ajax错误消息?

时间:2015-09-22 05:52:37

标签: jquery ruby-on-rails ruby ajax

脚本

 <script type="text/javascript">
  $('.v_name').each(function() {
    $(this).on('ajax:success', function(event, data, status, xhr) {
      var dat, id ;
      id = $(this).attr('id');
     dat = JSON.parse(data);
      $('#' + id).html(dat.name.toUpperCase());
    });

  });
</script>

index.html.erb

 <% @vehicles.each do |vehicle| %>
<tr>
    <td><%= best_in_place vehicle,:name, class: "v_name", id: vehicle.id%></td>
    <td><%= link_to '<i class="fa fa-trash-o"></i>'.html_safe, vehicle, method: :delete,  remote: true, data: { confirm: "Are you sure to delete <b>\"#{vehicle.name}\"?</b>", commit: "OK" }, title: "Delete Vehicle", class: "btn btn-danger delete_vehicle" %>

    </td>
</tr>       
<%end%>

vehicles_controller.rb

    class VehiclesController < ApplicationController
  before_action :set_vehicle, only: [:show, :edit, :update, :destroy]
  load_and_authorize_resource

   # skip_before_action :verify_authenticity_token

  # GET /vehicles
  # GET /vehicles.json
  def index
    @q = Vehicle.search(params[:q])
    @vehicles = @q.result(:distinct => true).order_by([:updated_at, :desc]).page(params[:page]).per(5)
    @vehicle = Vehicle.new
  end

  # GET /vehicles/1
  # GET /vehicles/1.json
  def show
  end

  # GET /vehicles/new
  def new

  end

  # GET /vehicles/1/edit
  def edit
  end

  # POST /vehicles
  # POST /vehicles.json
  def create
    params[:vehicle][:name] = params[:vehicle][:name].upcase if !params[:vehicle][:name].nil?
    @vehicle = Vehicle.new(vehicle_params)
    @vehicles = Vehicle.all.order_by([:updated_at, :desc]).page(params[:page]).per(5)
    respond_to do |format|
      if @vehicle.save
        format.html { redirect_to :back, notice: 'Vehicle was successfully created.' }
        format.json { render action: 'index', status: :created, location: @vehicle }
        format.js
      else
        format.js
        format.html { render action: 'new' }
        format.json { render json: @vehicle.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /vehicles/1
  # PATCH/PUT /vehicles/1.json
  def update
        params[:vehicle][:name] = params[:vehicle][:name].upcase if !params[:vehicle][:name].nil?

    respond_to do |format|

      if @vehicle.update(vehicle_params)
        format.html { redirect_to @vehicle, notice: 'Vehicle was successfully updated.' }
        format.json {render json: @vehicle, status: :ok}
      else
        format.html { render action: 'edit' }
        format.json { render json: @vehicle.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /vehicles/1
  # DELETE /vehicles/1.json
  def destroy
    @vehicle.destroy
    respond_to do |format|
      format.html { redirect_to vehicles_url, notice: "#{@vehicle.name} deleted successfully" }
      format.json { head :no_content }
      format.js { render :layout => false}
    end
  end

  def vehicle_search

    @q = Vehicle.search(params[:q])
    @vehicles = @q.result(:distinct  => true).order_by([:updated_at, :desc]).page(params[:page]).per(5)

    respond_to do |format|
      format.html
      format.js
    end
  end
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_vehicle
      @vehicle = Vehicle.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def vehicle_params
      params.require(:vehicle).permit(:name, :created_at, :updated_at)
    end
end

vehicle.rb

 class Vehicle
  include Mongoid::Document
    include Mongoid::Timestamps

  field :name, type: String
  validates :name, presence: true, uniqueness: true, :format => {:with => /[1-9a-zA-Z][0-9a-zA-Z ]{3,}/}
  has_many :pre_processings
  has_many :batch_counts


end

如何在rails中显示Ajax错误消息?

这里我使用上面的脚本更新名称为大写。如果有重复的名称,它会通过Ajax显示错误消息,这是可能的。

提前谢谢。

3 个答案:

答案 0 :(得分:4)

<强>的Ajax

大多数人认为JQuery Ajax函数的error钩子提供了处理通过它传递的异常的能力,但实际上它是为了显示 ajax 错误而设计的。 IE如果您从服务器收到响应,它将被归类为&#34; success&#34;,除非您在标题中明确设置了错误响应。

这是我自己的经验,可能是错误的,但我发现最好的方法是区分success函数中返回的消息,除非你能够在你的内容中呈现错误Rails响应。

This tutorial解释了我的意思:

-

他在没有设置错误标题的情况下处理错误的例子:

if @order.save
   #...
else
   format.json { render :json => { :error => @order.errors } }
end


$(document).on "ajax:success", "form", (xhr, data, response) ->
   if data.error
      for message of data
         $('#errors ul').append '<li>' + data.error[message] + '</li>'

这是因为您没有发送错误的请求标头,这就是您正在做的事情。

如果你发送一个错误的请求标题(IE ajax选择它是错误的),你可以使用以下内容:

if @order.save
   #...
else
   format.json { render :json => { :error => @order.errors.full_messages }, :status => 422 }
end


$(document).on "ajax:error", "form", (evt, xhr, status, error) ->
   errors = xhr.responseJSON.error
   for message of errors
      $('#errors ul').append '<li>' + errors[message] + '</li>'

正如其他评论中所述,这允许您使用Rails' ajax functionalityajax:error回调:

#app/assets/javascripts/application.js.erb
$("document).on('ajax:error', '.v_name', function(evt, xhr, status, error) {
      // process errors here
});

另外,您需要修复代码的某些部分:

  1. 脚本
  2. 永远不要把你的脚本&#34; in-line&#34;在你看来,正如你现在所做的那样。 Rails使用unobtrusive Javascript,这意味着您的所有JS逻辑都应保存在/assets/javascripts文件中,如下所示:

     #app/assets/javascripts/application.js
     $(".v_name").on('ajax:success', function(event, data, status, xhr) {
          var dat, id ;
          id = $(this).attr('id');
          dat = JSON.parse(data);
          $('#' + id).html(dat.name.toUpperCase());
     });
    

    您也不需要使用.each函数 - Javascript绑定到特定元素。如果将它绑定到元素的类型,则会为其每个实例调用它。

    1. ERB
    2. 视图中,您使用以下代码:

      <% @vehicles.each do |vehicle| %>
      <tr>
          <td><%= best_in_place vehicle,:name, class: "v_name", id: vehicle.id%></td>
          <td><%= link_to '<i class="fa fa-trash-o"></i>'.html_safe, vehicle, method: :delete,  remote: true, data: { confirm: "Are you sure to delete <b>\"#{vehicle.name}\"?</b>", commit: "OK" }, title: "Delete Vehicle", class: "btn btn-danger delete_vehicle" %>
      
          </td>
      </tr>       
      <%end%>
      

      这是非常偶然的(你可以做得更干净):

      <% @vehicles.each do |vehicle| %>
         <%= content_tag :tr do %>
            <%= content_tag :td, best_in_place(vehicle, :name, class: "v_name", id: vehicle.id) %>
            <%= content_tag :td, link_to('<i class="fa fa-trash-o">&nbsp;</i>', vehicle, method: :delete,  remote: true, data: { confirm: "Are you sure to delete <b>\"#{vehicle.name}\"?</b>", commit: "OK" }, title: "Delete Vehicle", class: "btn btn-danger delete_vehicle") %>
         <% end %>
      <% end %>
      

      您还应注意,您应将ERB和HTML代码尽可能分开。例如,在link_to中,您有以下内容:

      link_to('<i class="fa fa-trash-o">&nbsp;</i>'
      

      这是非常糟糕的做法。我已经离开了它&#34;按原样#34;现在因为你似乎正在使用一些需要这种结构的网络字体图标。但是,将来,您需要避免将纯HTML放入ERB。 Rails拥有尽可能多的helpers来保持干净。

      1. DRY
      2. 虽然您的控制器似乎没问题,但您确实需要尽可能将其作为DRY。 DRY (Don't Repeat Yourself)意味着尽可能多地将thins放入自己的方法中,而不是为了它而具体,并且通常尽可能地保留controller as thin

        例如......

        #app/controllers/vehicles_controller.rb
        class VehiclesController < ApplicationController
            before_action :set_vehicle_search, only: [:index, :vehicle_search]
            private
        
            def vehicle_search
               @q = Vehicle.search(params[:q])
            end
        end
        

答案 1 :(得分:0)

我将在ajax中添加以下脚本错误函数。它起作用了我。

   $('.v_name').each(function() {
   $(this).on('ajax:error', function(event, xhr, data, status) {
        alert("Please find out error duplicate values!");

    });
  });

答案 2 :(得分:0)

您可以在between创建文件,并在成功或显示错误消息时编写javascript代码以更新视图