web-dev-qa-db-fra.com

Ruby syntaxe: sortir du bloc 'each .. do ..'

Je développe une application Ruby on Rails. Ma question concerne davantage la syntaxe Ruby.

J'ai une classe modèle avec une méthode de classe self.check:

class Cars < ActiveRecord::Base
  ...
  def self.check(name)
     self.all.each do |car|
          #if result is true, break out from the each block, and return the car how to...
          result = SOME_CONDITION_MEET?(car) #not related with database
     end

     puts "outside the each block."
  end
end

Je voudrais arrêter/sortir du bloc eachne fois le result est vrai (c'est casser le each bloquer si car.name est identique au paramètre namene fois) ET renvoie le car qui provoque le résultat true. Comment éclater en Ruby code?

45
Mellon

Vous pouvez rompre avec le mot clé break. Par exemple

[1,2,3].each do |i|
  puts i
  break
end

affichera 1. Ou si vous souhaitez renvoyer directement la valeur, utilisez return.

Depuis que vous avez mis à jour la question, voici le code:

class Car < ActiveRecord::Base
  # …

  def self.check(name)
    self.all.each do |car|
      return car if some_condition_met?(car)
    end

    puts "outside the each block."
  end
end

Vous pouvez également utiliser Array#detect ou Array#any? Dans ce but.

93
tbuehlmann

Je fournis un mauvais exemple de code. Je ne trouve pas ou ne vérifie pas quelque chose directement dans la base de données. J'ai juste besoin d'un moyen de sortir du "chaque" bloc si une condition se réunit une fois et de retourner cette "voiture" qui provoque le vrai résultat.

Alors ce dont vous avez besoin c'est:

def check(cars, car_name)
  cars.detect { |car| car.name == car_name }
end

Si vous vouliez juste savoir s'il y avait une voiture avec ce nom, vous utiliseriez Enumerable#any?. En règle générale, utilisez Enumerable#each uniquement pour faire des effets secondaires, pas pour exécuter la logique.

12
tokland

Vous pouvez utiliser break mais ce que vous essayez de faire pourrait être fait beaucoup plus facilement, comme ceci:

def self.check(name)
  return false if self.find_by_name(name).nil?
  return true
end

Cela utilise la base de données. Vous essayez d'utiliser Ruby à un endroit où la base de données peut mieux le gérer.

Vous pouvez également utiliser break conditionnel:

break if (car.name == name)
1
davidb

vous pouvez utiliser include? méthode.

def self.check(name)
  cars.include? name
end

include? renvoie true si name est présent dans le tableau cars sinon il renvoie false.

1
Sayuj