iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🎲

[Notes] Rails Coding Patterns #2: Logical Operator ||

に公開

This is the second article in this series.

https://zenn.dev/adverdest/articles/c8bf3fa1ed1b7f

In this article, we will cover the logical operator ||.

Return Values of Expressions Using ||

A method of evaluation where the process ends as soon as the truth value of the entire expression is determined is called short-circuit evaluation.

sample.rb
nil || false # => false
false || nil # => nil

Using this, you can assign values in a single line like this:

sample.rb
user = find_user("Alice") || find_user("Bob") || find_user("Carol")

Self-Assignment

The following code means that if the variable limit is nil or false, the value 10 will be assigned to it.

sample.rb
limit ||= 10

limit ||= 10 is evaluated as follows:

sample.rb
limit || limit = 10

If limit is truthy, it finishes by simply evaluating limit. On the other hand, if limit is falsy, limit = 10 is executed, making the default value of limit 10.

When you see the code X ||= A, it is helpful to mentally translate it as "if variable X is nil or false, assign A to X."

Default Values

I used the term "default value" in the section on self-assignment. This can also be used with short-circuit evaluation. The following article is about JavaScript, but the concept is the same.

https://qiita.com/Yametaro/items/17f9b2baa67440b8664a

sample.rb
 user_name = current_user.name || "ゲスト"

If the logged-in user exists, the user's name is displayed; otherwise, "ゲスト" (Guest) is displayed as the default.

presence

Rails has a method called presence.

https://apidock.com/rails/Object/presence

This method returns the receiver itself if present? is true. Let's look at an example from the Rails API documentation.

sample.rb
 region = params[:state].presence || params[:country].presence || 'US'

If both params[:state] and params[:country].presence are nil, the default value 'US' is assigned to region.

Without using presence, if params[:state] arrives as [], for instance, this is neither false nor nil, so [] would be assigned. However, by using presence, you can avoid this.

Here is an example of how I used it:

sample.rb
 books = Books.where(available_flag = true)
 available_books = books.presence || 'ありません'

With books alone, it becomes [] when no books match, but by adding presence, you can avoid this and display an alternative message instead.

Memoization

Memoization is the practice of storing a calculated value so that the same calculation does not need to be performed again when it is called for the second time and onwards.

sample.rb
def twitter_data
  @twitter_data ||= begin
    # (processing)
  end
end

Writing it this way ensures that the processing is executed only the first time the twitter_data method is called. For subsequent calls, it simply returns the value stored in @twitter_data, which improves the program's performance.

There is one thing to keep in mind: if @twitter_data ends up being nil, the processing will still be executed in subsequent calls. To avoid this, you need to write it as follows:

sample.rb
def twitter_data
  return @twitter_data if instance_variable_defined?(:@twitter_data)
  @twitter_data ||= begin
    # (processing)
  end
end

https://moneyforward.com/engineers_blog/2019/03/15/ruby-code-4/

https://docs.ruby-lang.org/ja/latest/method/Object/i/instance_variable_defined=3f.html

References

Ruby Programming for Professionals [Revised 2nd Edition]: From Language Specifications to Test-Driven Development and Debugging Techniques

Discussion