我有after_destroy
回调,如此:
after_destroy :update_max_depth_on_entire_tree
定义是:
def update_max_depth_on_entire_tree
root = self.root
root.check_or_update_max_tree_depth
root.descendants.each { |c|
c.check_or_update_max_tree_depth
}
end
def check_or_update_max_tree_depth
update_columns(max_tree_depth: last_depth)
end
def last_depth
if child_ids.empty?
return depth
else
return children.map{|c| c.last_depth}.max
end
end
每当我尝试删除一个对象时,都会收到此错误:
ActiveRecord::ActiveRecordError at /posts/detecting-ramsay-is-offered-ceo-job
cannot update on a new record object
这是服务器日志的样子:
Started DELETE "/posts/detecting-ramsay-is-offered-ceo-job" for 127.0.0.1 at 2015-01-05 09:56:24 -0500
Processing by PostsController#destroy as HTML
Parameters: {"authenticity_token"=>"2xRY+A=", "id"=>"detecting-ramsay-is-offered-ceo-job"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 ORDER BY "users"."id" ASC LIMIT 1
(2.9ms) SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 3]]
(2.4ms) SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'editor') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 3]]
Post Load (0.9ms) SELECT "posts".* FROM "posts" WHERE "posts"."slug" = 'detecting-ramsay-is-offered-ceo-job' ORDER BY "posts"."id" ASC LIMIT 1
(0.2ms) BEGIN
Post Load (5.2ms) SELECT "posts".* FROM "posts" WHERE (("posts"."ancestry" ILIKE '69/%' OR "posts"."ancestry" = '69'))
Role Load (0.6ms) SELECT "roles".* FROM "roles" WHERE "roles"."resource_id" = $1 AND "roles"."resource_type" = $2 [["resource_id", 69], ["resource_type", "Post"]]
FriendlyId::Slug Load (2.9ms) SELECT "friendly_id_slugs".* FROM "friendly_id_slugs" WHERE "friendly_id_slugs"."sluggable_id" = $1 AND "friendly_id_slugs"."sluggable_type" = $2 ORDER BY "friendly_id_slugs".id DESC [["sluggable_id", 69], ["sluggable_type", "Post"]]
SQL (1.5ms) DELETE FROM "friendly_id_slugs" WHERE "friendly_id_slugs"."id" = $1 [["id", 47]]
SQL (1.2ms) DELETE FROM "posts" WHERE "posts"."id" = $1 [["id", 69]]
Post Load (0.4ms) SELECT "posts"."id" FROM "posts" WHERE "posts"."ancestry" = '69'
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 281ms
ActiveRecord::ActiveRecordError - cannot update on a new record object:
activerecord (4.1.6) lib/active_record/persistence.rb:272:in `update_columns'
() /app/models/post.rb:122:in `check_or_update_max_tree_depth'
() /app/models/post.rb:130:in `update_max_depth_on_entire_tree'
如何调用此方法,或实现我想要实现的目标(即,在删除1个节点时更新树上所有节点上的属性)而不会出现此错误?
修改1
这就是我的路线:
mark_as_published_post_path PUT /posts/:id/mark_as_published(.:format) posts#mark_as_published
mark_as_unpublished_post_path PUT /posts/:id/mark_as_unpublished(.:format) posts#mark_as_unpublished
posts_path GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post_path GET /posts/new(.:format) posts#new
edit_post_path GET /posts/:id/edit(.:format) posts#edit
post_path GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
status_path GET /:status(.:format) posts#status {:status=>/confirmed|unconfirmed|corroborated/}
GET /posts/:id(.:format) redirect(301, /%{id})
GET /:friendly_id(.:format) posts#show
GET /posts/:friendly_id(.:format) posts#show
GET /rbt/:name(.:format) redirect(301)
GET /:name(.:format) posts#show
root_path GET / posts#index
这就是我PostController#Destroy
的样子:
def destroy
@post = Post.find(params[:id])
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Report was successfully destroyed.' }
format.json { head :no_content }
end
end
修改2
我认为问题在于这部分代码:
def check_or_update_max_tree_depth
update_columns(max_tree_depth: last_depth)
end
错误似乎是在链路的某处遇到新记录,并且它无法对作为新记录的对象执行update_columns(max_tree_depth: last_depth)
。
我该如何解决这个问题?
答案 0 :(得分:0)
这个问题已经变得有点大,但我会试一试。 。
您的最新更新表明您的问题在于update_columns
无法处理新记录。为什么不使用update_attributes`呢?
变化:
def check_or_update_max_tree_depth
update_columns(max_tree_depth: last_depth)
end
为:
def check_or_update_max_tree_depth
update_attributes(max_tree_depth: last_depth)
end
我发现了一个与update_columns
未在2012年开始处理新记录的问题相关的讨论,其中可能包含一些可帮助您重构部分应用程序的信息,这些信息会给您带来麻烦:{{3} }
<强>更新强>
你已经回答了这个问题,但只是为了完成主义而注意到这里。 。
另一种解决方案是简单地向update_columns
方法添加条件,检查对象是否为new_record?
:
if new_record?
return
else
update_column(:max_tree_depth, last_depth)
end
答案 1 :(得分:0)
我最终通过做一些事情来弄明白。将update_column(max_tree_depth: last_depth)
包含在new_record?
支票中,如下所示:
def check_or_update_max_tree_depth
if new_record?
return
else
update_column(:max_tree_depth, last_depth)
end
end
解决了这个错误。
我遇到的另一个错误是每当我的回调遇到一条记录是根记录时,因为我在祖先中使用:adopt
孤儿策略来确定如何处理已删除的帖子,它正在从post.children
创建一条新记录,并将它们分配给root并将所有内容扔进wack。
所以我只修改了我的代码:
def update_max_depth_on_entire_tree
if max_tree_depth <= 0
return
else
root = self.root
root.check_or_update_max_tree_depth
root.descendants.each { |c|
c.check_or_update_max_tree_depth
}
end
end
这似乎已经做到了。