使用Rails 4.不确定我是否过于雄心勃勃。我有以下示例:
params[:shop].each_with_index do |id, index|
Shop.update(id, position: index + 1)
end
其中params[:shop] = [1, 3, 5, 7]
是shop
个ID的列表。上面的代码应该触发4个单独的SQL,如下所示:
Shop Load (0.7ms) SELECT `shops`.* FROM `shops` WHERE `shops`.`id` = 1 LIMIT 1
(0.2ms) BEGIN
SQL (0.5ms) UPDATE `shops` SET `position` = 1 WHERE `shops`.`id` = 1
Shop Load (0.7ms) SELECT `shops`.* FROM `shops` WHERE `shops`.`id` = 3 LIMIT 1
(0.2ms) BEGIN
SQL (0.5ms) UPDATE `shops` SET `position` = 2 WHERE `shops`.`id` = 3
Shop Load (0.7ms) SELECT `shops`.* FROM `shops` WHERE `shops`.`id` = 5 LIMIT 1
(0.2ms) BEGIN
SQL (0.5ms) UPDATE `shops` SET `position` = 3 WHERE `shops`.`id` = 5
Shop Load (0.7ms) SELECT `shops`.* FROM `shops` WHERE `shops`.`id` = 7 LIMIT 1
(0.2ms) BEGIN
SQL (0.5ms) UPDATE `shops` SET `position` = 4 WHERE `shops`.`id` = 7
有没有办法将SQL缩减为一个语句?
答案 0 :(得分:0)
那里有一个update_all
,所以这不是你的问题。请参阅文档here
您可以执行以下操作:
shop_ids = [1,3,5,4]
Shop.where("id in (?)", company_ids).update_all(...)
更大的问题是你在update_all中放了什么,因为你是基于数组中shop_id的索引位置。如果你知道你只是想要上下颠倒所有这些 - 你当然可以像
那样做shop_ids = [1,3,5,4]
Shop.where("id in (?)", company_ids).update_all("position = position + 1")
除此之外 - 你可能做的事情可能不多。
答案 1 :(得分:-1)
这是不问题的答案,而是对我为什么不对params哈希执行操作的评论的扩展。
白名单简单地说允许某些属性。这样做的原因是为了防止用户将属性插入到params中。假设您在帖子控制器上并将所有内容列入白名单,用户可以插入以下参数:
"user":"123", "password":"abc"
如果您只是使用params哈希更新您的模型,您可能只是覆盖了用户123的密码,现在就是' abc' - 一个巨大的安全漏洞。
如果您将params严格限制为Post模型上的属性,则会缩小用户可能造成伤害的范围。但是,减少损害的范围并不意味着预防。
在您提供的代码中,您假设id
将是一个数字。如果它不是什么?这就是SQL注入成为问题的地方*。 See this page for examples。如果用户注入恶意SQL,他们可能会获得整个数据转储,包括敏感信息。如果您打算使用params,请小心。
其他资源:Ruby On Rails Security Guide
* Rails清理了很多数据,但有些部分留给sql注入,比如update_all