我有一个before_save
,需要先创建/保存记录。
如果记录不是before_save
,那么我是否可以执行new
,如果记录不是after_save
那么?
修改1
这是我的方法和回调:
after_save :check_or_update_max_tree_depth
def check_or_update_max_tree_depth
self.max_tree_depth = self.last_depth
end
def last_depth
if child_ids.empty?
return root.max_tree_depth
else
return children.map{|c| c.last_depth}.max
end
end
创建新记录后,它不会保存max_tree_depth
属性。这是刚刚创建的新记录的示例:
[155] pry(main)> p = Post.last
Post Load (1.9ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT 1
=> #<Post id: 63, title: "JPS counter sues", photo: nil, body: "JPS has officially filed a countersuit on crashees...", created_at: "2015-01-05 05:30:39", updated_at: "2015-01-05 05:30:39", user_id: 3, ancestry: "46/54/59", file: nil, status: 1, slug: "jps-counter-sues", publication_status: 1, has_eyewitness: false, youtube_embed_code: "", soundcloud_embed_code: "", ancestry_depth: 3, max_tree_depth: nil>
[156] pry(main)> p.last_depth
Post Load (0.5ms) SELECT "posts"."id" FROM "posts" WHERE "posts"."ancestry" = '46/54/59/63'
Post Load (1.0ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1 [["id", 46]]
=> 4
[157] pry(main)> p.child_ids
Post Load (1.5ms) SELECT "posts"."id" FROM "posts" WHERE "posts"."ancestry" = '46/54/59/63'
=> []
[158] pry(main)> p.root.max_tree_depth
Post Load (1.5ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1 [["id", 46]]
=> 4
[159] pry(main)> p.max_tree_depth
=> nil
请注意,其他所有内容似乎都返回了正确的值。只是每当创建新记录时,它都不会保存它。
如果我使用了before_save
,它会正确更新属性 - 但仅限于现有记录。在以前没有保存过的全新记录中,ancestry gem
会引起人们的注意。
答案 0 :(得分:1)
以下内容应达到您的目的:
before_save :method_name
after_save :method_name
private
def method_name
if new_record? || @already_ran
@already_ran = nil # using 'remove_instance_variable' would be better
return
end
# your method's original code
@already_ran = true # pick a better variable name
end
@already_ran
只是为了确保在保存后保存AND之前不会调用相同的方法。如果在保存之前和之后运行它两次是安全的,那么你可以简化这样的事情:
before_save :method_name
after_save :method_name
private
def method_name
return if new_record?
# your method's original code
end
或者,根据您的使用情况,您可以保留after_save
并完全删除before_save
。但我假设您已经考虑过其他简化选项,例如只有一个after_save
或after_create
回调。
答案 1 :(得分:0)
您所要做的就是重新加载对象以保持持久性
after_save :check_or_update_max_tree_depth
def check_or_update_max_tree_depth
self.reload
self.max_tree_depth = self.last_depth
self.save
end
def last_depth
if child_ids.empty?
return root.max_tree_depth
else
return children.map{|c| c.last_depth}.max
end
end