Ruby on rails Ruby三元条件似乎在不在parens内时被忽略?

Ruby on rails Ruby三元条件似乎在不在parens内时被忽略?,ruby-on-rails,ruby,if-statement,ternary-operator,Ruby On Rails,Ruby,If Statement,Ternary Operator,我试图理解为什么将这一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通过了测试,一切都很好,但当我试图将其变成这样的三元表达式时,它无法

我试图理解为什么将这一
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)>'

我想这一定是什么东西,但我就是看不见。感谢n advance花时间回复并帮助我学习。

这是一件优先事项<代码>?:的优先级高于
=
,允许您根据条件分配:

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")
它将首先对艺术家进行评估。通过找到_,并在此基础上确定条件;如果它找到了什么,它会尝试评估
@songs=a.songs
,但
a
尚未分配<代码>a正在等待条件的结果,并将收到
@songs=a.songs
的值或
重定向到
的值。。。当条件完成时

从风格上讲,我更愿意将此保留为
,如果。。。然后。。。其他的结束
,假设您没有使用
?:
的结果。三元条件运算符通常在条件返回的值相关且两个分支都是相对简单的表达式时使用。如果。。。然后。。。其他的结束
如果未使用返回值(如在代码中),或者如果分支由多个简单表达式组成,尤其是如果多行或多语句:

foo =
  if bar
     do_something
     do_something_else(bar)
     final_result
  else
     do_another_thing
     skip_something_else
     the_other_final_result
  end

仅供参考,这种方式是对三元组的严重误用。它被用作一个表达式(产生一个值)。但你把它当作一种陈述,有副作用。@SergioTulentsev你能读懂我的心思:DThanks@Sergio Tulentsev,明白了。谢谢你花时间解释@Amadan。有一件事让我非常困惑,那就是我认为测试失败的地方是找不到艺术家的地方,但失败清楚地表明这是一个有艺术家的地方。真的很晚了。。。好吧,我没有借口。“三元条件运算符通常在条件返回的值相关时使用”是一个好的观点,我将把它作为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