我有两种模式:
class User < ActiveRecord::Base
belongs_to :group, dependent: :destroy
validates :login, presence: true
before_create :add_group
private
def add_group
create_group(name: login)
end
end
和
class Group < ActiveRecord::Base
has_one :user
end
当我尝试创建用户时,我得到SystemStackError: stack level too deep
。
所以我改变了这样的add_group回调:
def add_group
create_group(name: login) unless group
end
现在,它保存了用户并正确设置了group_id,但是在没有验证的情况下创建了User的第二个空记录。 SQL:
>> u = User.create!(login: "foo")
(0.7ms) BEGIN
SQL (2.2ms) INSERT INTO "groups" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "foo"], ["created_at", "2016-04-06 10:09:52.981954"], ["updated_at", "2016-04-06 10:09:52.981954"]]
Group Load (1.2ms) SELECT "groups".* FROM "groups" WHERE "groups"."id" = $1 LIMIT 1 [["id", 1453]]
SQL (2.0ms) INSERT INTO "users" ("login", "created_at", "updated_at", "group_id") VALUES ($1, $2, $3, $4) RETURNING "id" [["login", "foo"], ["created_at", "2016-04-06 10:09:52.923926"], ["updated_at", "2016-04-06 10:09:52.923926"], ["group_id", 1453]]
SQL (1.4ms) INSERT INTO "users" DEFAULT VALUES RETURNING "id"
(9.1ms) COMMIT
最后一个INSERT INTO用户表是奇数。 我无法弄清楚为什么会发生这种情况......
我找到了两个解决方案:
class Group < ActiveRecord::Base
has_one :user, autosave: false
##OR##
has_one :usr, class_name: "User"
# has_one :user, class_name: "User" works weird too
end
但它并不能说服我。
有什么不对?在Rails 4.0一切正常。
更新1
好的,我找到了另外两个解决方案:
class User < ActiveRecord::Base
belongs_to :group, dependent: :destroy
validates :login, presence: true
before_create :add_group
private
def add_group
self.group = Group.create(name: login)
# OR #
assign_attributes(group: Group.create(name: login))
end
end
class Group < ActiveRecord::Base
has_one :user
end
但我仍然不明白为什么它表现得如此奇怪......特别是这个额外的空记录并由has_one :usr, class_name: "User"
修复
答案 0 :(得分:0)
您只应构建您的论坛,并让AR为您保留:
class User < ActiveRecord::Base
belongs_to :group, dependent: :destroy
validates :login, presence: true
before_create :add_group
private
def add_group
build_group(name: login)
end
end
调用create_group
时,它会再次重新启动AR验证,从而重新启动before_create
挂钩。
答案 1 :(得分:0)
答案就在这里:autosave: false
这意味着当您向用户添加组时,rails会将de group_id分配给用户(belongs_to),因此尝试再次保存de object,我认为因为您仍处于创建行为中,所以#save会触发再次使用after_create,你得到的堆栈级别太深了。
改为使用group.create(name: login)
。