rails update_attribute永远循环

时间:2017-05-13 13:14:30

标签: ruby-on-rails

update_attribute调用永远创建循环。

可能是什么原因?
也许这是一个变化:
Prevent infinite loop when updating attributes within after_commit, :on => :create

ruby​​ --version

ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux]

命令

rails new loop
cd loop
bundle install
bundle exec rails g scaffold User
bundle exec rails db:migrate
bundle exec rails g migration add_name_to_users name:string
bundle exec rails db:migrate

将以下内容添加到app / models / user.rb

class User < ApplicationRecord
  before_create: create_temp_name

  def create_temp_name
    update_attribute :name, 'temp name'
  end
end

运行bundle exec rails s,访问http://localhost:3000/users/new并按下创建按钮。

结果:

SystemStackError (stack level too deep):

app/models/user.rb:5:in `create_temp_name'
app/models/user.rb:5:in `create_temp_name'

捆绑列表

  • actioncable(5.1.1)
  • actionmailer(5.1.1)
  • actionpack(5.1.1)
  • actionview(5.1.1)
  • activejob(5.1.1)
  • activemodel(5.1.1)
  • activerecord(5.1.1)
  • activesupport(5.1.1)
  • addressable(2.5.1)
  • arel(8.0.0)
  • bindex(0.5.0)
  • builder(3.2.3)
  • bundler(1.14.6)
  • byebug(9.0.6)
  • capybara(2.13.0)
  • childprocess(0.7.0)
  • coffee-rails(4.2.1)
  • coffee-script(2.4.1)
  • coffee-script-source(1.12.2)
  • concurrent-ruby(1.0.5)
  • erubi(1.6.0)
  • execjs(2.7.0)
  • ffi(1.9.18)
  • globalid(0.4.0)
  • i18n(0.8.1)
  • jbuilder(2.6.4)
  • 听(3.1.5)
  • 丝瓜(2.0.3)
  • mail(2.6.5)
  • method_source(0.8.2)
  • mime-types(3.1)
  • mime-types-data(3.2016.0521)
  • mini_portile2(2.1.0)
  • minitest(5.10.2)
  • multi_json(1.12.1)
  • nio4r(2.0.0)
  • nokogiri(1.7.2)
  • public_suffix(2.0.5)
  • puma(3.8.2)
  • rack(2.0.2)
  • rack-test(0.6.3)
  • rails(5.1.1)
  • rails-dom-testing(2.0.3)
  • rails-html-sanitizer(1.0.3)
  • railties(5.1.1)
  • rake(12.0.0)
  • rb-fsevent(0.9.8)
  • rb-inotify(0.9.8)
  • ruby​​_dep(1.5.0)
  • ruby​​zip(1.2.1)
  • sass(3.4.23)
  • sass-rails(5.0.6)
  • selenium-webdriver(3.4.0)
  • spring(2.0.1)
  • spring-watcher-listen(2.0.1)
  • 链轮(3.7.1)
  • sprockets-rails(3.2.0)
  • sqlite3(1.3.13)
  • thor(0.19.4)
  • thread_safe(0.3.6)
  • 倾斜(2.0.7)
  • turbolinks(5.0.1)
  • turbolinks-source(5.0.3)
  • tzinfo(1.2.3)
  • uglifier(3.2.0)
  • web-console(3.5.1)
  • websocket(1.2.4)
  • websocket-driver(0.6.5)
  • websocket-extensions(0.1.2)
  • xpath(2.0.0)

1 个答案:

答案 0 :(得分:1)

您不应该在回调中调用update_attribute,因为save方法将在before_create回调执行后调用。您可以在回调中分配像name = 'temp_name'这样的值,并允许在对象创建期间保存它。 update_attributesave的别名,因此在回调完成后再次调用save函数之前,您可以保存初始化对象,从而导致无限循环/堆栈溢出。

为了帮助理解这一点,如果在rails控制台中实例化一个新的空白对象,然后在其中一个属性上运行update_attribute,您会注意到该对象已保存/分配了一个id:< / p>

# rails c

user = User.new
user.persisted?
  => false
user.update_attribute('name', 'Nick')
user.persisted?
  => true

因此,通过调用update_attribute,您将调用before_create回调的其他实例,因为在模型允许在update_attribute调用期间将对象保存到数据库之前,它会调用before_create回调。