首页 > 解决方案 > Rails 冲突 ajax 和 URI.encode

问题描述

我有一个搜索字符串,它通过我的控制器连接到我的书面库,并向第三方 api 发送获取请求。表格:

<%= form_with(:url => url_for(:controller => 'orders', :action => 'find_drug'), method: "get") do %>
    <%= text_field_tag :drug_name, nil, class: "search_drug", placeholder:"Find drug..." %>
    <%= button_to "Find", nil, class: "search_drug_button" %>
<% end %>

阿贾克斯:

$('document').ready(function() {
    $('.search_drug_button').click(function(){
        $.ajax({
                url: 'orders/find_drug',
            }).done(function(data) {
                console.log(data);
            });
        });
    });

控制器订单控制器:

def find_drug
        response = ApiParser::Parser.new
        drugs = response.get_drug(params[:drug_name]).response

        respond_to do |format|
            format.json { render json: drugs.body}
        end
    end

我的库中的方法(使用 HTTParty gem 编写):

module ApiParser
    class Parser
        include HTTParty
        ...
        def get_drug(drug)
            options = "?search.drugs={\"ls\": \"#{URI.encode(drug)}\"}"                                 
            self.class.get(options, format: :json)
        end
        ...    
    end
end

在控制台中,发送了 2 个请求(其中一个表单,直接使用代码 200 发送到控制器,第二个通过 ajax)并且 ajax 给了我一个错误 500

NoMethodError in OrdersController#find_drug

undefined method `gsub' for nil:NilClass
Extracted source (around line #305):

#303         unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false)
#304       end
*305       str.gsub(unsafe) do
#306         us = $&
#307         tmp = ''
#308         us.each_byte do |uc|

Extracted source (around line #104):

#102     def escape(*arg)
#103       warn "#{caller(1)[0]}: warning: URI.escape is obsolete" if $VERBOSE
*104       DEFAULT_PARSER.escape(*arg)
#105     end
#106     alias encode escape
#107     #

Extracted source (around line #38):
                                             **#this is my code**
*38             options = "?search.drugs={\"ls\": \"#{URI.encode(drug)}\"}"                                 
#39             self.class.get(options, format: :json)

控制台 Chrome 200 中的请求:

...localhost:3000/orders/find_drug?utf8=%E2%9C%93&drug_name=%D1%8F%D1%80%&authenticity_token=Ndao2...

500:

...localhost:3000/orders/find_drug

如果在控制器中,而不是params[:drug_name],我只需传递我想要查找的字符串,则使用代码 200 的两个查询都可以工作。写完整个问题后,我认为我的 ajax 没有收到这个特定的params[:drug_name],并且无法搜索空值(但不完全是)。刚开始使用 javascript

我试图执行这样一个 Ajax 请求:

$('document').ready(function() {
  $('.search_drug_button').click(function(e){
    e.preventDefault();
    $.ajax({
      url: 'orders/find_drug',
      data: new FormData($(this).closest("form")[0])
    }).done(function(data){
      console.log(data);
    });
  });
});

但我有一个错误

jquery-3.3.1.min.js:2 Uncaught TypeError: Illegal invocation
    at i (jquery-3.3.1.min.js:2)
    at jt (jquery-3.3.1.min.js:2)
    at Function.w.param (jquery-3.3.1.min.js:2)
    at Function.ajax (jquery-3.3.1.min.js:2)
    at HTMLInputElement.<anonymous> (Аптечная_сеть:551)
    at HTMLInputElement.dispatch (jquery-3.3.1.min.js:2)
    at HTMLInputElement.y.handle (jquery-3.3.1.min.js:2)

标签: ruby-on-railsajaxformsrequest

解决方案


首先让我告诉你为什么你的代码不起作用。

  • 您正在同时使用表单和 jQuery
  • 如果你想使用 jQuery,你应该阻止提交按钮上发生的所有默认操作,event.preventDefault();否则你将发送两个请求,一个是默认表单提交,另一个是 jQuery。

解决方案:

您可以通过使用 rails 默认功能js.erb

让这个工作。

在您的控制器代码中使用它。

def find_drug
  response = ApiParser::Parser.new
  @drugs = response.get_drug(params[:drug_name]).response
end
  • 注释掉你所有的ajax代码。
  • 将您的代码替换为form_with(url: '/orders/find_drug', method: :get)
  • 在订单文件夹中创建一个文件为find_drug.js.erb
  • console.log('<%= @data %>');_find_drug.js.erb

现在检查一下。如果您仍然面临问题,请告诉我。


推荐阅读