How do you assign a variable with the result of a if..else block? How do you assign a variable with the result of a if..else block? ruby ruby

How do you assign a variable with the result of a if..else block?


As an alternative to the syntax in badp's answer, I'd like to propose:

@products =   if params[:category]    Category.find(params[:category]).products  else    Product.all  end

I claim this has two advantages:

  1. Uniform indentation: each level of logical nesting is indented by exactly two spaces (OK, maybe this is just a matter of taste)
  2. Horizontal compactness: A longer variable name will not push the indented code past the 80 (or whatever) column mark

It does take an extra line of code, which I would normally dislike, but in this case it seems worthwhile to trade vertical minimalism for horizontal minimalism.

Disclaimer: this is my own idiosyncratic approach and I don't know to what extent it is used elsewhere in the Ruby community.

Edit: I should mention that matsadler's answer is also similar to this one. I do think having some indentation is helpful. I hope that's enough to justify making this a separate answer.


As a Ruby programmer, I find the first clearer. It makes it clear that the whole expression is an assignment with the thing assigned being determined based on some logic, and it reduces duplication. It will look weird to people who aren't used to languages where everything is an expression, but writing your code for people who don't know the language is not that important a goal IMO unless they're specifically your target users. Otherwise people should be expected to have a passing familiarity with it.

I also agree with bp's suggestion that you could make it read more clearly by indenting the whole if-expression so that it is all visually to the right of the assignment. It's totally aesthetic, but I think that makes it more easily skimmable and should be clearer even to someone unfamiliar with the language.

Just as an aside: This sort of if is not at all unique to Ruby. It exists in all the Lisps (Common Lisp, Scheme, Clojure, etc.), Scala, all the MLs (F#, OCaml, SML), Haskell, Erlang and even Ruby's direct predecessor, Smalltalk. It just isn't common in languages based on C (C++, Java, C#, Objective-C), which is what most people use.


I don't like your use of whitespace in your first block. Yes, I'm a Pythonista, but I believe I make a fair point when I say the first might look confusing in the middle of other code, maybe around other if blocks.

How about...

@products = if params[:category] Category.find(params[:category]).products            else                 Product.all            end

@products = if params[:category]              Category.find(params[:category]).products            else                              Product.all            end

You could also try...

@products = Product.all #unless a category is specified:@products = Category.find(params[:category]).products if params[:category]

...but that's a bad idea if Product.all actually is a function-like which could then be needlessly evaluated.