ruby-on-rails 如何在Rails中一次更新多条记录?

vktxenjb  于 2023-02-26  发布在  Ruby
关注(0)|答案(2)|浏览(187)

我想从rails代码中删除below循环。

list=Student.find_by_sql("select study_id from students where id in (1,2,3,4,5)") 

list.each do |val|
  Subject.where(:sub_id=>val).update({:sub_code=> 'SO1'})
end

我如何重写这些代码而不循环list,并直接在where条件中传递list?

13z8s7eq

13z8s7eq1#

假设您有不遵循Rails约定的主键,并且正确配置了SubjectStudent之间的关联,那么您将能够编写:

student_ids = (1..5) # or just an array of ids
Subject.joins(:students)
       .where(students: { id: student_ids })
       .update_all(sub_code: 'S01')

值得注意的是,update_all只创建一个查询,直接通过SQL过滤和更新记录。但是因为update_all只生成一个SQL查询,所以它绕过并跳过了验证和回调。当没有依赖于该属性的验证或回调时,这对于简单的单个属性更新来说可能是可以的。
但是,当您希望确保验证和回调运行时,您无法避免将记录加载到内存中,并使用update甚至update!,如下所示:

Subject.joins(:students)
       .where(students: { id: student_ids })
       .each do |subject|
  subject.update_all(sub_code: 'S01')
end

这个版本仍然比问题中的版本好,因为它只需要一次查询就可以将所有记录加载到内存中,并且只对它们进行单独更新,而问题中的版本则是通过单独的查询将每条记录加载到内存中。

06odsfpq

06odsfpq2#

您可以连接科目和学生表以查询需要更新的科目,如下所示:

subjects = Subject.joins('INNER JOIN students ON subjects.sub_id = students.study_id').where('students.id IN (?)', [1, 2, 3, 4, 5])

subjects.update(sub_code: 'SO1')

相关问题