Rails表单和对不同控制器的自定义Ajax调用

Rails Forms and Custom Ajax Calls to a Different Controller

本文关键字:自定义 Ajax 调用 控制器 表单 Rails      更新时间:2023-09-26

我有3个模型,通道,标签然后是通道标签,它们有一个有多个通过关系设置如下:

通道模型

has_many :tags, :through => :channel_tags, :dependent => :destroy
has_many :channel_tags, :dependent => :destroy
<<p> 标记模型/strong>
has_many :channel_tags, :dependent => :destroy
has_many :channels, :through => :channel_tags, :dependent => :destroy

通道标签模型

belongs_to :channel
belongs_to :tag

在我的编辑频道表单上,我有一个文本输入供用户输入标签,然后是一个自定义js插件,该插件对数据库进行ajax调用,以检查与搜索匹配的现有标签,如果没有找到结果,用户可以将搜索词添加为新标签,这是任何博客平台的经典功能。但是,我在添加新标签时遇到了一些问题。我有以下JS做一个帖子:

var name = _ts.$input.val(),
    auth_token = $('input[name="authenticity_token"]').val();
$.post('/tags/?&authenticity_token=' + auth_token, { name : name }, function(data) {
     console.log(data);
});

当我第一次这样做的时候,我得到的错误是它是一个无效的authenticity_token,我假设这是因为它是因为代码是一个编辑通道形式,而不是一个新的标签形式。我看到有人建议在标签控制器中添加以下内容:

protect_from_forgery with: :null_session

那工作,虽然我不确定这是最好的解决方案?

但是现在我得到一个400错误说:

ActionController::ParameterMissing in TagsController#create
param is missing or the value is empty: tag

我很有信心这是因为我的标签控制器中有以下内容:

 def tag_params
    params.require(:tag).permit(:name,
                                :slug
    )
  end

我不确定如何围绕它工作?是否有一个特殊的方法与自定义JS与rails交互?我已经阅读了关于使用form_for远程的文档,但这并不适用于我想做的事情。

任何建议或指导将不胜感激!!

多谢大卫。

首先,您应该从meta标记(从header)获得您的真实性令牌,而不是从隐藏的输入,因为令牌始终存在于header中。然后您应该设置AJAX调用,以便X-CSRF-Token头将与您的所有请求一起发送:

$.ajaxSetup({
  beforeSend: function(xhr) {
    var token = $('meta[name="csrftoken"]').attr('content');
    xhr.setRequestHeader('X-CSRF-Token', token);
  }
}); 

现在可以保留原来的protect_from_forgery方法。我不认为在这里使用protect_from_forgery with: :null_session是个好主意。然后,您应该实现其他授权机制。

关于你的参数,根据要求:

$.post('/tags', { name : name }, function(data) {
  console.log(data);
});

TagsController#create接收到的参数将是{name: 'tag name'}。所以params.require(:tag)肯定是缺失的。你应该使用;params.permit(:name)代替。但是,我认为,这是更好的,遵循Rails的默认值,改变你的AJAX调用代替:

$.post('/tags', { tag: { name : name } }, function(data) {
  console.log(data);
});