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)
- rubyzip(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_attribute
是save
的别名,因此在回调完成后再次调用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
回调。