遇到一个奇怪的问题,我有一个task model
和video model
,一对多的关系,现在是想在软删除task
的时候,获取它所有的video
,但是由于会将相应的video
的task_id
置为空,导致获取到的视频结果也是空的。
函数代码如下
def destroy_tasks ids
not_delete_ids = Task.ids
correct_ids = ids & not_delete_ids
correct_ids.sort!
videos = Video.where(:task_id => correct_ids)
names = Task.where(:id => correct_ids).pluck(:name)
destroy_params = Array.new
names.each do |name|
temp = Hash.new
t = Time.now
temp[:name] = "#{name}-#{t.to_i}"
temp[:delete_at] = t
destroy_params.push temp
end
Task.update(correct_ids, destroy_params)
Video.where(:task_id => correct_ids).update_all(:task_id => nil)
respond_to do |format|
format.html { redirect_to tasks_url, notice: "#{I18n.t('notice.destroy', model: Task.model_name.human)}" }
format.json { render :destroy_tasks, locals: {ids: correct_ids, action: 'destroy', videos: videos }}
end
end
看日志发现,获取video
的 sql 语句是在最后执行的,尽管它在程序中的语句十分靠前
Started POST "/tasks/handle" for 127.0.0.1 at 2015-12-09 15:53:18 +0800
Processing by TasksController#handle_tasks as JSON
Parameters: {"utf8"=>"✓", "tasks"=>"113,", "next_action"=>"destroy"}
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
(0.5ms) SELECT `tasks`.`id` FROM `tasks` WHERE (delete_at IS NULL)
(0.4ms) SELECT `tasks`.`name` FROM `tasks` WHERE (delete_at IS NULL) AND `tasks`.`id` = 113
Task Load (0.5ms) SELECT `tasks`.* FROM `tasks` WHERE (delete_at IS NULL) AND `tasks`.`id` = 113 LIMIT 1
(0.6ms) BEGIN
Task Exists (0.6ms) SELECT 1 AS one FROM `tasks` WHERE (`tasks`.`name` = BINARY '测试任务51-1449647598' AND `tasks`.`id` != 113) LIMIT 1
SQL (0.5ms) UPDATE `tasks` SET `name` = '测试任务51-1449647598', `delete_at` = '2015-12-09 15:53:18', `updated_at` = '2015-12-09 15:53:18' WHERE `tasks`.`id` = 113
(65.7ms) COMMIT
SQL (47.4ms) UPDATE `videos` SET `videos`.`task_id` = NULL WHERE (delete_at IS NULL) AND `videos`.`task_id` = 113
Video Load (0.5ms) SELECT `videos`.* FROM `videos` WHERE (delete_at IS NULL) AND `videos`.`task_id` = 113
Rendered tasks/destroy_tasks.json.jbuilder (1.8ms)
Completed 200 OK in 140ms (Views: 4.4ms | ActiveRecord: 117.2ms)
把Video.where(:task_id => correct_ids).update_all(:task_id => nil)
语句放在函数最下面就没问题。
似乎是因为 ruby 变量只有在第一次使用的时候才会确定它的值?依稀有这个概念,但是不太确定。
在 rails console 下面写了一个 test 函数测试,能获取正确的 videos,然而在删除第一个p videos
后,只会得到空结果。
def test id
task = Task.find id
videos = task.videos
p videos
t = Time.now
task.update(:delete_at => t, :name => "#{task.name}-#{t.to_i}")
Video.where(:task_id => id).update_all(:task_id => nil)
p videos
end