Ruby语法:从'each ... do ..'块中突破

时间:2011-12-14 09:46:50

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.1

我正在开发 Ruby on Rails 应用。我的问题更多是关于 Ruby 语法。

我有一个带有类方法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

我想停止/突破each阻止一次 result true (这会打破{{1}如果eachcar.name参数一次相同,则阻止,并返回导致 true 结果的name。如何在Ruby代码中突破?

5 个答案:

答案 0 :(得分:90)

您可以使用break关键字。例如

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

将输出1。或者,如果要直接返回值,请使用return

由于您更新了问题,因此代码为:

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

虽然您也可以使用Array#detectArray#any?来实现此目的。

答案 1 :(得分:11)

  

我提供了一个错误的示例代码。我不是直接找到或检查的东西   来自数据库。我只是需要一种方法来突破“每个”块   一些条件遇到一次并返回导致真实的“汽车”   结果

然后你需要的是:

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

如果您只想知道是否有任何带有该名称的汽车,那么您可以使用Enumerable#any?。根据经验,仅使用Enumerable#each来执行副作用,而不是执行逻辑。

答案 2 :(得分:1)

您可以使用break,但您尝试做的事情可以更轻松地完成,例如:

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

这使用数据库。您正试图在数据库可以更好地处理它的地方使用Ruby。

您还可以使用break条件:

break if (car.name == name)

答案 3 :(得分:1)

您可以使用include?方法。

def self.check(name)
  cars.include? name
end
如果include?数组中存在true,则

name会返回cars,否则会返回false

答案 4 :(得分:0)

我必须做同样的事情,而且我还是空白。因此,尽管这是一个非常老的问题,但这是我的答案:

由于从积木块返回很狡猾(没人喜欢,我认为规则将要改变,这使它更加烦恼),这是一个更好的选择:

collection.inject(nil) do |_acc, item|
  output = expensive_operation(item)
  break output if output
end

请注意,有很多变体。例如,如果您不希望使用附带变量,并且不介意在某些情况下启动第二个循环,则可以像这样反转它:

collection.inject(nil) do |acc, item|
  break acc if acc
  expensive_operation(item)
end