首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从回调方法中叠加得太深

从回调方法中叠加得太深
EN

Stack Overflow用户
提问于 2016-07-14 19:01:35
回答 1查看 121关注 0票数 0

我有四种运动模式,黄金,银牌和青铜,一对一的关系,体育和其他三种。运动的每一个实例都必须有一个金色、银色和青铜的实例,其中三个是使用运动模型中的回调函数创建的。这些回调函数是一个抛出我能够跟踪的错误的函数,因为生成的rails错误堆栈只是一行。

我的密码

模型

运动

代码语言:javascript
复制
class Sport < ActiveRecord::Base
    validates :sportname, presence: true, 
                         uniqueness: { case_sensitive: false }

   has_one :gold, inverse_of: :sport, :dependent => :destroy
   has_one :silver, inverse_of: :sport, :dependent => :destroy
   has_one :bronze, inverse_of: :sport, :dependent => :destroy

   accepts_nested_attributes_for :gold
   accepts_nested_attributes_for :silver
   accepts_nested_attributes_for :bronze


   after_validation :build_default_medals, on: :create

   def build_default_medals
    self.build_gold
    self.build_silver
    self.build_bronze
  end
end

黄金

代码语言:javascript
复制
class Gold < ActiveRecord::Base

  belongs_to :sport    #, inverse_of: :gold
  validates_associated :sport, presence: true

  belongs_to :team, inverse_of: :golds, counter_cache: true 
  validates_associated :team,  :if => :create, allow_nil: true  

  accepts_nested_attributes_for :team
  accepts_nested_attributes_for :sport
end

银牌

代码语言:javascript
复制
class Silver < ActiveRecord::Base

  belongs_to :sport   #, inverse_of: :silver   
  validates_associated :sport, presence: true

  belongs_to :team, inverse_of: :silvers, counter_cache: true 
  validates_associated :team, :if => :create, allow_nil: true    

  accepts_nested_attributes_for :team
  accepts_nested_attributes_for :sport
end

青铜

代码语言:javascript
复制
class Bronze < ActiveRecord::Base
  belongs_to :sport   #, inverse_of: :bronze
  validates_associated :sport, presence: true

  belongs_to :team, inverse_of: :bronzes, counter_cache: true 
  validates_associated :team,  :if => :create, allow_nil: true 

  accepts_nested_attributes_for :team
  accepts_nested_attributes_for :sport
 end

回调after_validation :build_default_medals, on: :create就是错误所在,在我的日志中产生了这个错误。

代码语言:javascript
复制
 Started POST "/admin/sports" for 127.0.0.1 at 2016-07-14 14:52:22 -0400
 Processing by Admin::SportsController#create as HTML
 Parameters:{"utf8"=>"√",authenticity_token"=>"jss1O4bSJd3hcqxuSpu/KAxaowB7d
g5pLZw55oGDf1M=", "sport"=>{"sportname"=>"boxing"}, "commit"=>"Create Sport"}
User Load (1.0ms)  SELECT  `users`.* FROM `users`  WHERE `users`.`id` = 1       LIMIT 1  (0.0ms)  BEGIN
Sport Exists (1.0ms)  SELECT  1 AS one FROM `sports`  WHERE `sports`.`sportname` = 'boxing' LIMIT 1
SQL (1.0ms)  INSERT INTO `sports` (`created_at`, `sportname`, `updated_at`) VALUES ('2016-07-14 18:52:22', 'boxing', '2016-07-14 18:52:22')
SQL (15.1ms)  UPDATE `sports` SET `created_at` = '2016-07-14 18:52:22', `id` = 13, `sportname` = 'boxing', `updated_at` = '2016-07-14 18:52:22' WHERE `sports`.`id` = 13
SQL (1.0ms)  INSERT INTO `golds` (`created_at`, `sport_id`, `updated_at`) VALUES ('2016-07-14 18:52:22', 13, '2016-07-14 18:52:22')
SQL (1.0ms)  UPDATE `sports` SET `created_at` = '2016-07-14 18:52:22', `id` =13, `sportname` = 'boxing', `updated_at` = '2016-07-14 18:52:22' WHERE `sports`.`id` = 13
SQL (1.0ms)  INSERT INTO `silvers` (`created_at`, `sport_id`, `updated_at`) VALUES ('2016-07-14 18:52:22', 13, '2016-07-14 18:52:22')
SQL (1.0ms)  UPDATE `sports` SET `created_at` = '2016-07-14 18:52:22', `id` =13, `sportname` = 'boxing', `updated_at` = '2016-07-14 18:52:22' WHERE `sports`.`id` = 13
SQL (1.0ms)  INSERT INTO `bronzes` (`created_at`, `sport_id`, `updated_at`) VALUES ('2016-07-14 18:52:22', 13, '2016-07-14 18:52:22')  (72.2ms)  
ROLLBACK
Completed 500 Internal Server Error in 213ms

SystemStackError (stack level too deep):  actionpack (4.1.8) lib/action_dispatch/middleware/reloader.rb:79


Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/_source.erb (2.0ms)
Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (4.0ms)
Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (7.0ms)
Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.8/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (145.1ms)

我很好奇为什么回调会在插入后触发更新,以及究竟是什么触发了ROLLBACKStack Level Too Deep的无限循环。任何洞察力都是值得赞赏的。谢谢。

编辑

使用after_create :build_default_medals代替after_validation :build_default_medals, on: :creation产品

代码语言:javascript
复制
  Started POST "/admin/sports" for 127.0.0.1 at 2016-07-14 16:19:24 -0400
  Processing by Admin::SportsController#create as HTML
  Parameters: {"utf8"=>"√","authenticity_token"=>"3LrwB6+nD9PJ9EwxEgIGhN3rVHP3UPLOHUz9MXWRJ4Y=", "sport"=>{"sportname"=>"dancing"}, "commit"=>"Create Sport"}
  User Load (1.0ms)  SELECT  `users`.* FROM `users`  WHERE `users`.`id` = 1 LIMIT 1   (0.0ms)  BEGIN
  Sport Exists (1.0ms)  SELECT  1 AS one FROM `sports`  WHERE `sports`.`sportname` = 'dancing' LIMIT 1
  SQL (1.0ms)  INSERT INTO `sports` (`created_at`, `sportname`,`updated_at`) VALUES ('2016-07-14 20:19:24', 'dancing', '2016-07-14 20:19:24') 
 Gold Load (2.0ms)  SELECT  `golds`.* FROM `golds`  WHERE `golds`.`sport_id` =8 LIMIT 1
 Silver Load (1.0ms)  SELECT  `silvers`.* FROM `silvers`  WHERE `silvers`.`sport_id` = 8 LIMIT 1
 Bronze Load (1.0ms)  SELECT  `bronzes`.* FROM `bronzes`  WHERE `bronzes`.`sport_id` = 8 LIMIT 1
 (45.5ms)  COMMIT

用于undefined method 'create' for #<Gold:0x63bf820>编辑

代码语言:javascript
复制
def build_default_medals
  #Gold.create(sport: self, team: nil)
  #Silver.create(sport: self, team: nil)
  #Bronze.create(sport: self, team: nil)
  self.create_gold(team: nil)
  self.create_silver(team: nil)
  self.create_bronze(team: nil)
end
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-14 19:44:11

替换

代码语言:javascript
复制
after_validation :build_default_medals, on: :create

使用

代码语言:javascript
复制
after_create :build_default_medals

你正在尝试建立相关的模型,而运动仍然是一个新的记录,而不是一个持久化的记录。validates_associated :sport, presence: true会导致循环依赖,并会产生错误。

我复制并测试了这一变化。会很好的。

对于保存的对象,请使用self.create_gold而不是self.build_gold,如下所示

代码语言:javascript
复制
  def build_default_medals
    self.create_gold
    self.create_silver
    self.create_bronze
  end

同时去除黄金,银和青铜模型的accepts_nested_attributes_for :sport。参考- https://github.com/rails/rails/issues/7809

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38382240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档