提问人:Sanjay Salunkhe 提问时间:9/4/2023 最后编辑:Sanjay Salunkhe 更新时间:9/7/2023 访问量:80
即使在事务回滚 [closed] 后,也会保存 Rails has_one关联
Rails has_one association is saved even after the transaction is rollback [closed]
问:
我正在将 rails 3 应用程序升级到 rails 5 版本。我有has_one和belongs_to协会。我正在交易块中保存记录。在 Rails 5 中,我观察到,如果事务被回滚,则空数据会入到“任务”表中。在 rails 3 的情况下,这不会发生。这是 Rails 5 中的预期行为吗?我不想破坏现有的功能,那么有没有办法在 Rails 5 中保留 Rails 3 的行为?
下面是产生此问题的示例代码。
class Student < ApplicationRecord
has_one :task
end
class Task < ApplicationRecord
belongs_to :student
validates_presence_of :name
end
student = Student.first
student.name = nil
def student.testing
begin
ActiveRecord::Base.transaction do
t = Task.new
t.name = 'ddd'
t.student = self
t.save!
puts "raising exception"
raise "exception"
end
rescue => e
end
end
student.testing
student.save!
答:
0赞
smathy
9/4/2023
#1
假设“belongs_to表”是(为什么不在这里只说“学生”或“任务”?)那么是的,你显示的代码应该会导致“空数据”被保存到表中。students
students
不知道为什么你认为代码周围的回滚事务块会影响代码?Task#save!
student.name = nil; student.save!
评论
0赞
Sanjay Salunkhe
9/4/2023
他们为什么在我更改与has_many的关系时没有插入空记录?为什么只有在has_one的情况下才会插入此 null 记录?
0赞
smathy
9/5/2023
你的问题是关于 Rails 3 和 5 的,如果你想问一些关于 vs 的问题,那么你需要更新你的问题,这样我们才能看到你在说什么。has_one
has_many
1赞
Alex
9/4/2023
#2
从这个例子中,我只能找出一个问题——那就是 rails 如何检测关联。inverse_of
有一个
class Task < ApplicationRecord
belongs_to :student
end
class Student < ApplicationRecord
has_one :task, dependent: :destroy
end
>> Task.reflect_on_association(:student).inverse_of.name
=> :task
因为inverse_of是设置的,所以当你赋值给逆时也会赋值 - :student
task.student
student.task
student = Student.first
student.association(:task).target #=> nil
Task.new(student: student)
student.association(:task).target #=> #<Task:0x00007f2333a18ad0 id: nil, name: nil, student_id: 2>
# something to save ---------------------^
student.save!
# INSERT INTO "tasks" ("name", "student_id") VALUES (?, ?) [["name", nil], ["student_id", 2]]
如果回滚任务事务,对象仍分配给 ,并且在保存父级时保存新关联,这并不重要。这做了完全相同的事情:student.task
student = Student.first
Task.transaction do
Task.create!(student: student)
raise ActiveRecord::Rollback
end
student.save!
TRANSACTION (0.1ms) begin transaction
Task Create (0.2ms) INSERT INTO "tasks" ("name", "student_id") VALUES (?, ?) [["name", nil], ["student_id", 2]]
TRANSACTION (0.1ms) rollback transaction
TRANSACTION (0.0ms) begin transaction
Task Create (0.1ms) INSERT INTO "tasks" ("name", "student_id") VALUES (?, ?) [["name", nil], ["student_id", 2]]
TRANSACTION (9.8ms) commit transaction
无逆向
class Task < ApplicationRecord
belongs_to :student, inverse_of: false
end
行为与以下方面相同:has_many
Task.reflect_on_association(:student).inverse_of #=> nil
student = Student.first
student.association(:task).target #=> nil
Task.new(student: student)
student.association(:task).target #=> nil
# nothing to save -----------------------^
student.save!
有很多
class Task < ApplicationRecord
belongs_to :student
end
class Student < ApplicationRecord
has_many :tasks, dependent: :destroy
end
Task.reflect_on_association(:student).inverse_of # => nil
student = Student.first
student.association(:tasks).target #=> []
Task.new(student: student)
student.association(:tasks).target #=> []
# nothing to save ------------------------^
student.save!
与反向
class Task < ApplicationRecord
belongs_to :student, inverse_of: :tasks
end
Task.reflect_on_association(:student).inverse_of.name #=> :tasks
student = Student.first
student.association(:tasks).target #=> []
Task.new(student: student)
student.association(:tasks).target #=> [#<Task:0x00007f007d82b2c8 id: nil, name: nil, student_id: 2>]
# something to save ----------------------^
student.save!
# INSERT INTO "tasks" ("name", "student_id") VALUES (?, ?) [["name", nil], ["student_id", 2]]
评论
def
rescue
student.task