gpt4 book ai didi

ruby-on-rails - 在 Rails 关系上使用 Ruby 的 select 方法并更新它

转载 作者:数据小太阳 更新时间:2023-10-29 07:15:18 25 4
gpt4 key购买 nike

我有一个用户之前“投票”的 ActiveRecord 关系...

@previous_votes = current_user.votes

我需要过滤这些以仅对当前“挑战”投票,因此 Ruby 的 select 方法似乎是最好的方法...

@previous_votes = current_user.votes.select { |v| v.entry.challenge_id == Entry.find(params[:entry_id]).challenge_id }

但是我还需要更新这些记录的属性,select 方法将我的关系变成了一个无法更新或保存的数组!

@previous_votes.update_all :ignore => false
# ...
# undefined method `update_all' for #<Array:0x007fed7949a0c0>

我如何像 select 方法那样过滤我的关系,但又不失去使用 ActiveRecord 更新/保存项目的能力?

在 Google 上四处寻找,似乎 named_scope 出现在所有类似问题的答案中,但我无法弄清楚它们是否可以具体完成我所追求的。

最佳答案

问题是 select 不是 SQL 方法。它获取所有记录并在 Ruby 端过滤它们。这是一个简化的示例:

votes = Vote.scoped
votes.select{ |v| v.active? }
# SQL: select * from votes
# Ruby: all.select{ |v| v.active? }

由于 update_all 是一种 SQL 方法,因此您不能在 Ruby 数组上使用它。您可以坚持在 Ruby 中执行所有操作,或将其中一些(全部)移动到 SQL 中。

votes = Vote.scoped
votes.select{ |v| v.active? }
# N SQL operations (N - number of votes)
votes.each{ |vote| vote.update_attribute :ignore, false }
# or in 1 SQL operation
Vote.where(id: votes.map(&:id)).update_all(ignore: false)

如果您实际上不使用获取的选票,那么在 SQL 端执行整个选择和更新会更快:

Vote.where(active: true).update_all(ignore: false)

虽然前面的示例与您的 select 配合得很好,但这个示例需要您根据 SQL 重写它。如果您已经在 Rails 模型中设置了所有关系,您可以大致如下进行:

entry = Entry.find(params[:entry_id])
current_user.votes.joins(:challenges).merge(entry.challenge.votes)
# requires following associations:
# Challenge.has_many :votes
# User.has_many :votes
# Vote.has_many :challenges

Rails 会为您构建合适的 SQL。但是,如果出现问题,您始终可以退回到手动编写 SQL。

关于ruby-on-rails - 在 Rails 关系上使用 Ruby 的 select 方法并更新它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16098974/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com