【发布时间】:2019-03-10 16:28:14
【问题描述】:
我试图理解为什么将此 if-then-else 行转换为三元表达式 (?:) 不起作用。我知道这可能不是最合适的代码,但我想了解发生了什么。
if a = Artist.find_by(id: params[:artist_id]) then @songs = a.songs else redirect_to(artists_path, alert: "Artist not found") end
上面的if-then-else 通过了测试,一切都很好,但是当我尝试将其设为像这样的三元表达式时,它无法按预期工作。
a = Artist.find_by(id: params[:artist_id]) ? @songs = a.songs : redirect_to(artists_path, alert: "Artist not found")
这给了我以下失败:
1) songs when nested under artists /artists/:artist_id/songs displays the songs with valid artist
Failure/Error: a = Artist.find_by(id: params[:artist_id]) ? @songs = a.songs : redirect_to(artists_path, alert: "Artist not found")
NoMethodError:
undefined method `songs' for nil:NilClass
# ./app/controllers/songs_controller.rb:4:in `index'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/etag.rb:24:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/conditionalget.rb:25:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/head.rb:13:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:225:in `context'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/session/abstract/id.rb:220:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/railties-4.2.5/lib/rails/rack/logger.rb:38:in `call_app'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/railties-4.2.5/lib/rails/rack/logger.rb:20:in `block in call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/railties-4.2.5/lib/rails/rack/logger.rb:20:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/runtime.rb:18:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/lock.rb:17:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/sendfile.rb:113:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/railties-4.2.5/lib/rails/engine.rb:518:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/railties-4.2.5/lib/rails/application.rb:165:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/urlmap.rb:66:in `block in call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `each'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `call'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-test-0.6.3/lib/rack/mock_session.rb:30:in `request'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-test-0.6.3/lib/rack/test.rb:244:in `process_request'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/rack-test-0.6.3/lib/rack/test.rb:58:in `get'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/capybara-2.5.0/lib/capybara/rack_test/browser.rb:60:in `process'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/capybara-2.5.0/lib/capybara/rack_test/browser.rb:35:in `process_and_follow_redirects'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/capybara-2.5.0/lib/capybara/rack_test/browser.rb:21:in `visit'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/capybara-2.5.0/lib/capybara/rack_test/driver.rb:42:in `visit'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/capybara-2.5.0/lib/capybara/session.rb:232:in `visit'
# /home/dapawn/.rvm/gems/ruby-2.3.3/gems/capybara-2.5.0/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
# ./spec/features/songs_spec.rb:13:in `block (4 levels) in <top (required)>'
如果a 是nil,它怎么能做三元表达式的真正部分?
如果我在这样的条件周围加上括号,它就可以正常工作:
(a = Artist.find_by(id: params[:artist_id])) ? @songs = a.songs : redirect_to(artists_path, alert: "Artist not found")
我认为它必须是某种优先级的东西,但我就是看不到它。提前感谢您抽出时间回复并帮助我学习。
【问题讨论】:
-
JFYI,这种方式是对三元的严重误用。它旨在用作表达式(产生一个值)。但是您将其用作声明,有副作用。
-
@SergioTulentsev 你读懂了我的想法:D
-
谢谢@Sergio Tulentsev,点了。
标签: ruby-on-rails ruby if-statement ternary-operator