ruby-on-rails 在fetch调用之后,有没有一种方法可以呈现js.erb?

xzabzqsa  于 2023-08-08  发布在  Ruby
关注(0)|答案(4)|浏览(128)

在我的Rails应用程序中,我想在fetch调用后呈现js.erb部分,但由于某些原因我不明白它不起作用。如果你能帮我,那就太好了。
在视图中,一个事件触发这个函数,它基本上执行一个获取请求:

function updateState(id, state){
      const csrfToken = document.querySelector('meta[name="csrf-token"]').attributes
          .content.value;
      fetch(window.location.origin + "/update_state", {
          method: "POST",
          headers: {
            'Accept': "JS",
            "Content-Type": "application/json",
            "X-CSRF-Token": csrfToken
          },
          body: JSON.stringify({'id': id, 'state': state}),
          credentials: "same-origin"
        })
}

字符串
然后在我的控制器中:

def update_state
    @model = Model.find(params[:id])
    authorize @model
    @model.update(state: params[:state])

    respond_to do |format|
      format.html { redirect_to xxx }
      format.js
    end
  end


在我的js.erb文件中:

console.log('hello');


但是,在这种情况下,我从服务器那里得到了一个错误:ActionController::UnknownFormat位于'response_to do'行|格式|我有一种感觉,服务器不理解fetch的头:'Accept':“JS”
当我查看服务器的日志时:

Started POST "/update_state" for 127.0.0.1 at 2019-04-04 11:22:49 +0200
Processing by ModelsController#update_state as JS


但我认为Rails并不认识它。我该怎么做?
我在控制器中也尝试了这个:

def update_state
    @model = Model.find(params[:id])
    authorize @model
    @model.update(state: params[:state])
    render 'update_state.js', layout: false
  end


它不会触发错误。我在客户端收到了js.erb。但是,它不会执行(console.log不执行)。
你知道吗?非常感谢你的帮助。

vsmadaxz

vsmadaxz1#

我可以反过来处理。我从来没有成功过js. erbb。
所以我使用了一个fetch调用,并在文本中给出了响应:

function updateState(id, state){
  const csrfToken = document.querySelector('meta[name="csrf-token"]').attributes
      .content.value;
  fetch(window.location.origin + "/update_state", {
      method: "POST",
      headers: {
        'Accept': "JS",
        "Content-Type": "application/json",
        "X-CSRF-Token": csrfToken
      },
      body: JSON.stringify({'id': id, 'state': state}),
      credentials: "same-origin"
    }).then(response => response.text())
      .then(data => {
       div.inserAdjacentHTML('XXX', data);
    });
}

字符串
然后在控制器/动作中:

def update_state
    @model = Model.find(params[:id])
    authorize @model
    @model.update(state: params[:state])
    render 'update_state.js', layout: false, content_type: "text/plain"
  end


这样,就能奏效了。希望对你有帮助。

3htmauhk

3htmauhk2#

  • 编辑:查看编辑,以获得手动触发.js.erb文件的完整解决方案。*

有同样的问题,实际上这里有两个问题。你是对的,你的头不是。这些触发.js.erb的标题对我来说很有效,看起来很正确:

'dataType': 'json',
'contentType': 'application/json; charset=utf-8',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': - your CSRF method to get the token -

字符串
但是第二个触发js响应,你的respond_to块:

respond_to do |format|
  format.html { redirect_to xxx }
  format.js
end


必须先有format.js。由于Rails对HTML有一个响应,所以它会首先用HTML响应,并且似乎甚至不寻找下一个格式块。

respond_to do |format|
  format.js
  format.html { redirect_to xxx }
end


希望有帮助:-)

编辑2018年13月11日

嘿,好久不见!同样的问题再次发生在我身上,我自己之前的答复并没有解决这个问题。和您一样,.js.erb文件被渲染,但什么也没有发生,console.log也没有显示。所以我用remote: true创建了一个link_to,它触发了我的.js.erb文件并比较了请求。一切都是一样的,除了一件事:请求的类型。一个是fetch,另一个是xhr。看来.js.erb文件仅由xhr请求触发。因此,解决方案是构建一个旧的xhr请求,而不是fetch,如下所示:

const url = 'your_custom_path' // Build the url to fetch
    const csrf = document.querySelector('meta[name="csrf-token"]').getAttribute('content')

    let xhr = new XMLHttpRequest();

    // Will be a GET request here
    xhr.open('GET', url, false);
​    
    // Setting the headers
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.setRequestHeader('X-CSRF-Token', csrf);
    xhr.setRequestHeader('dataType', 'script');
​
    // What to do with the response
    xhr.onload = function() {
      let responseObj = xhr.response
      eval(responseObj) // You need to eval() manually the response for it to be executed
    }
​
    // Sending the request
    xhr.send()


希望它有帮助,甚至几个月后!;)

33qvvth1

33qvvth13#

我在Rails 6中使用fetch遇到了这个问题。我的问题通过简单地将format.js放在format.html之上就解决了。谢谢@holino。下面的fetch工作。

fetch(event.currentTarget.dataset.destroyPath, {
    method: 'DELETE',
    dataType: 'script',
    credentials: 'include',
    headers: {
      'X-CSRF-Token': csrf
    },
  })

字符串

lnlaulya

lnlaulya4#

你也可以考虑使用Rails.ajax,如下所示:

Rails.ajax({
  url: `/endpoint`,
  type: "get",
  data: new URLSearchParams({parameter_a: "data"}).toString(),
  accept: 'js',
  dataType: 'script',
  success: function(data) {},
  error: function(data) {}
})

字符串
如果您尝试使用fetch,您将遇到问题,因为您需要执行从服务器返回的JavaScript。使用远程时:true,rails-ujs实际上会插入一个脚本标记,并在视图中返回JS脚本,以便执行它(然后删除它):

# if it's a script, attach it to the DOM
script = document.createElement('script')
script.setAttribute('nonce', cspNonce())
script.text = response
document.head.appendChild(script).parentNode.removeChild(script)


如果你使用Rails.ajax,这个问题就可以解决了。

相关问题