我有 3 个模型, channel ,标签,然后是 channel 标签,它们有一个有很多直通关系,设置如下:
channel 模型
has_many :tags, :through => :channel_tags, :dependent => :destroy
has_many :channel_tags, :dependent => :destroy
标签模型
has_many :channel_tags, :dependent => :destroy
has_many :channels, :through => :channel_tags, :dependent => :destroy
channel 标签模型
belongs_to :channel
belongs_to :tag
在我的编辑 channel 表单上,我有一个文本输入,供用户输入标签,然后有一个自定义 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,我假设这是因为代码用于编辑 channel 表单而不是新标签表单。我读到了将以下内容添加到标签 Controller 的建议:
protect_from_forgery with: :null_session
虽然我不确定它是最好的解决方案,但它有效吗?
但现在我收到 400 错误:
ActionController::ParameterMissing in TagsController#create
param is missing or the value is empty: tag
我非常有信心这是因为我的标签 Controller 中存在以下内容:
def tag_params
params.require(:tag).permit(:name,
:slug
)
end
但是我不确定如何解决这个问题?有没有一种特殊的方法可以用自定义JS与rails交互?我已阅读有关将 form_for 与远程一起使用的文档,但这不适用于我想要做的事情。
任何建议或指导将不胜感激!!
非常感谢 大卫
最佳答案
首先,您应该从 meta
标记(来自 header )获取真实性 token ,而不是从隐藏输入中获取,因为 token 始终存在于 header 中。然后您应该设置 AJAX 调用,以便 X-CSRF-Token
header 将与您的所有请求一起发送:
$.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);
});
关于javascript - Rails 表单和对不同 Controller 的自定义 Ajax 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32638514/