通过rails 4

时间:2016-06-12 01:57:27

标签: ruby-on-rails-4

我有一个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未定义方法'%'

1 个答案:

答案 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将删除所有未列入白名单的参数。

建议:使用byebugbinding.pry等工具跟踪您的错误。这是一个非常方便的工具,应该毫不留情地使用。