L'essentiel est que vous ne devriez pas faire un retour anticipé lorsque vous prenez des notes en Ruby (probablement pas seulement en Ruby).
def user
  @user ||= begin
    user = User.find_or_initialize_by(id: 1)
    return user if user.persisted? #Ne pas retourner lors de la définition des variables d'instance
    
    user.save
    user
  end
end
def user
  @user ||= begin
    user = User.find_or_initialize_by(id: 1)
    if user.persisted?
      user
    else
      user.save
      user
    end
  end
end
#Ou
def user
  @user ||= begin
    user = User.find_or_initialize_by(id: 1)
    user.save if user.new_record?
    user
  end
end
Lorsque vous utilisez des mémos dans Ruby (Rails), vous pouvez écrire quelque chose comme ce qui suit.
def user
  @user ||= User.first
end
S'il y a plusieurs lignes, placez-les entre begin ~ ʻend`.
def user
  @user ||= begin
    user = user.find_or_initialize_by(id: 1)
    if user.persisted?
      user
    else
      user.save
      user
    end
  end
end
Utilisons le retour anticipé, qui est une technique de refactoring courante.
def user
  @user ||= begin
    user = User.find_or_initialize_by(id: 1)
    return user if user.persisted?
      
    user.save
    user
  end
end
À première vue, ça a l'air bien, mais quand j'exécute cette méthode sur la console des rails, ça ressemble à ceci:
[1] pry(main)> def user
[1] pry(main)*   @user ||= begin
[1] pry(main)*     user = User.find_or_initialize_by(id: 1)
[1] pry(main)*     return user if user.persisted?
[1] pry(main)*
[1] pry(main)*     user.save
[1] pry(main)*     user
[1] pry(main)*   end
[1] pry(main)* end
=> :user
[2] pry(main)> user
  User Load (3.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User:0x00007ff0b4d2e338
 id: 1,
 created_at: Tue, 09 Jun 2020 15:04:04 JST +09:00,
 updated_at: Tue, 09 Jun 2020 15:04:04 JST +09:00>
[3] pry(main)> user
  User Load (1.8ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User:0x00007ff0ad554740
 id: 1,
 created_at: Tue, 09 Jun 2020 15:04:04 JST +09:00,
 updated_at: Tue, 09 Jun 2020 15:04:04 JST +09:00>
Aucun mémo n'est fait et une requête est émise à chaque fois. Si vous vérifiez à nouveau la référence,
Manuel de référence Ruby 2.7.0 https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#return return Termine l'exécution de la méthode avec la valeur de l'expression comme valeur de retour.
Puisqu'il y a une instruction, la méthode ʻuser se termine au stade de return, et la variable d'instance de @ user reste nil`, donc le processus est exécuté à chaque fois.
C'est naturel quand vous y réfléchissez, mais soyez prudent car vous pouvez devenir accro à l'écriture que vous utilisez souvent des retours anticipés dans votre habitude.
Recommended Posts