我有一个ajax请求,如下所示
var user = $('#user_id').attr("data-user");
var data = {"message_attributes":
[{credits: 150}]
};
$.ajax({
url: "/messages/" + user,
type: "PUT",
data: JSON.stringify(data),
contentType: 'application/json',
dataType: 'html',
complete: function() {},
success: function(data, textStatus, xhr) {
alert("Updated!");
},
error: function() {
alert("Could not process your request!");
}
})
消息/:user_id路由到自定义更新操作
def custom_update
if Message.where('user_id = ?',params[:user_id]).update_all(params[:message_attributes])
respond_to do |format|
format.js { render :json => true }
end
else
respond_to do |format|
format.js { render :json => false }
end
end
end
注意:credits是Message模型的一个属性(即消息表中有credit列)
我希望custom_update操作是动态的,以便它根据messages_attributes包含的内容更新列。有时它会有积分,有时它会有我想通过ajax发送的Message模型的其他属性。 Message.where()。update_all(params [:message_attributes])应该能够识别它们并相应地更新它们。 我该怎么做呢?
使用上面的代码我收到了这个错误 “{Cred:150}”的NoMethodError未定义方法'%'
答案 0 :(得分:1)
在这种特殊情况下,问题是您尝试在update_all
中使用JSON。要使它工作,你应该JSON.parse(params[:message_attributes])
将你的JSON数组解码为ruby哈希。
另外,我认为在这种情况下不需要[]
围绕参数,因为你的所有参数都将使用相同的大括号({}
)。
您还可以将更新行更改为Message.where(user_id: params[:user_id]).update_all(params[:message_attributes])
以防止SQL注入。
警告:不要使用这样的原始参数。它们容易受到攻击,因为任何人都可以将它们更改为任何属性并更新所有Message
条记录。
改为使用白名单
def message_params
params.require(:message_attributes).permit(:credits, :param2, :param3)
end
然后
Message.where(user_id: params[:user_id]).update_all(message_params)
这样,没有人能够在更新中注入其他参数,因为message_params
将删除所有未列入白名单的参数。
建议:使用byebug
或binding.pry
等工具跟踪您的错误。这是一个非常方便的工具,应该毫不留情地使用。