用.js.erb和Rails实例变量响应AJAX Rails请求

问题描述 投票:0回答:1

我正在Rails中苦苦追求JS AJAX请求。有一个官方指南here,但将它与ES6 JS匹配时遇到了一些困难。提出请求后,我很难将事情传递回前端。

我进行了JS window.onload调用,因为我试图找到用户的屏幕尺寸(以及其他),并将其传递回Rails:

    let xhttp = new XMLHttpRequest();
    const url = "/users";
    xhttp.open("POST", url);
    // Some other things added to it...
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 201) {
            console.log(this.responseText);
       }
    };
    xhttp.send(JSON.stringify({user_info: userInfo}));

它正在向/ user发布有关会话的一些信息。一切顺利。注意console.log会跟踪响应,稍后我们将进行介绍。

在我的Rails控制器中:

def create
  user_info = params[:user_info].permit!
  user_info = user_info.to_s
  @fingerprint_user =  User.find_or_create_by(fingerprint: user_info)
  respond_to do |format|
    # NOTE: I have tried a few things here
    # format.html { redirect_to @fingerprint_user, notice: "Successfully identified user by fingerprint." }
    # format.js
    format.json { render json: @fingerprint_user, status: :created, head: :ok }
  end
end

JSON发送者工作正常。上面JS中的console.log正确地console.log记录了接收到的JSON。请求以201和JSON形式的@fingerprint_user实例变量响应。

我的问题是返回带有实例变量的ERB JS。如指南中所示,我尝试添加format.js。然后,请求返回200,以及我的views/users/create.js.erb文件的内容:

console.log("hello");

但是,实际上不是登录到控制台。

最后,我尝试使用所有格式字段(js,html和json)。这是我的show.html.erb

<p>Got user: <%= @fingerprint_user.to_s %> </p>

这是一个更好的views/users/create.js.erb文件,其中fingerprint是我的index.html.erb中的div:

console.log("hello");
$("<%= escape_javascript(render @fingerprint_user) %>").appendTo("#fingerprint");

再次,响应是200,以及适当的html,但这未在页面上呈现。

ruby-on-rails ajax xmlhttprequest erb ruby-on-rails-6
1个回答
0
投票

对JavaScript的AJAX请求的请求不同于对JSON的请求。您实际上不需要加载数据并进行解析,而是实际加载数据,然后通过各种技巧将其评估为当前页面上下文,例如将脚本标签附加到文档中。这是实际的Rails UJS implementation

processResponse = (response, type) ->
  if typeof response is 'string' and typeof type is 'string'
    if type.match(/\bjson\b/)
      try response = JSON.parse(response)
    else if type.match(/\b(?:java|ecma)script\b/)
      script = document.createElement('script')
      script.setAttribute('nonce', cspNonce())
      script.text = response
      document.head.appendChild(script).parentNode.removeChild(script)
    else if type.match(/\b(xml|html|svg)\b/)
      parser = new DOMParser()
      type = type.replace(/;.+/, '') # remove something like ';charset=utf-8'
      try response = parser.parseFromString(response, type)
  response

这就是十年前我们使用JSONP跨域进行AJAX调用来解决CSP的确切方法。

您可以使用以下方法在“原始ajax请求”中模拟相同的内容:

let xhttp = new XMLHttpRequest();
const url = "/users";
xhttp.open("POST", url);
// Some other things added to it...
xhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 201) {
    let script = document.createElement('script');
    script.innerHTML = data;
    document.querySelector('head').appendChild(script);
  }
};

但坦率地说,js.erb是一个可怕的想法。它使服务器和客户端的责任变得一团糟,并使您的代码很难遵循和推理,并将JS从资产/ Webpack管道中移出,并进入了一些程序垃圾脚本视图。

© www.soinside.com 2019 - 2024. All rights reserved.