[英]Ruby ternary condition seems to be ignored when not inside parens?
我試圖理解為什么將這個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
,它怎么能做三元表達式的真正部分?
如果我把parens放在這樣的條件下,它可以正常工作:
(a = Artist.find_by(id: params[:artist_id])) ? @songs = a.songs : redirect_to(artists_path, alert: "Artist not found")
我認為它必須是某種優先級的東西,但我只是看不到它。 非常感謝您花時間回復並幫助我學習。
這是一個優先事項。 ?:
優先級高於=
,允許您根據條件進行分配:
animal = is_dog ? "dog" : "not a dog"
可以理解地解析為
animal = (is_dog ? "dog" : "not a dog")
如果要在條件內分配,則需要括號:
(animal = find_animal("dog")) ? "found dog" : "no dog"
在你的情況下,
a = Artist.find_by(id: params[:artist_id]) ?
@songs = a.songs :
redirect_to(artists_path, alert: "Artist not found")
它將首先評估Artist.find_by
並根據該決定條件; 如果它發現的東西,它試圖評估@songs = a.songs
,但是a
尚未分配 。 a
正在等待條件的結果,並且在條件完成時將接收@songs = a.songs
的值或redirect_to
的值。
從風格上來說,我寧願把這個留下來, if ... then ... else ... end
,因為你沒有使用結果?:
。 當條件返回的值相關時,通常使用三元條件運算符,並且兩個分支都是相對簡單的表達式。 我會使用if ... then ... else ... end
如果沒有使用返回值(如代碼中),或者如果分支包含多個簡單表達式,特別是多線或多線聲明:
foo =
if bar
do_something
do_something_else(bar)
final_result
else
do_another_thing
skip_something_else
the_other_final_result
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.