如何在Ruby中使用多个#select块?

iyr7buue  于 2022-12-22  发布在  Ruby
关注(0)|答案(4)|浏览(129)

假设我有一个记录列表,如:

transactions = Transaction.all

我有以下示例方法@currency, @geo, @industry。我想选择符合以下条件的记录:

  • 选择字段currency等于@currency的所有交易,除非@currency为nil,在这种情况下,我们将忽略该条件(currency为nil时表示所有货币)
  • 选择字段geo等于@geo的所有交易,除非@geo为空。
  • 选择字段industry等于@industry的所有交易,除非@industry为空。

我尝试了多个#select,但没有运气的东西:

transactions.select{ |i| (i.currency == @currency) unless @currency.nil? }.
        .select{ |i| (i.geo == @geo) unless @geo.nil? }.
        .select{ |i| (i.industry == @industry) unless @industry.nil? }
fslejnso

fslejnso1#

您的示例的问题是,如果@currencynil,则unless @currency.nil?将返回nil(这是falsey),这与您的意图相反。
您应该改用||

transactions.select{ |i| (i.currency == @currency) || @currency.nil? }.
        select{ |i| (i.geo == @geo) || @geo.nil? }.
        select{ |i| (i.industry == @industry) || @industry.nil? }

在这种情况下,如果@currencynil,则第一个条件将返回true,并且所有元素将通过select框到下一个...
另一个选择是运行selectonly 参数不是nil .在这种情况下,你需要把这一行分成几个单独的块:

transactions.select!{ |i| (i.currency == @currency) } unless @currency.nil?
transactions.select!{ |i| (i.geo == @geo) } unless @geo.nil?
transactions.select!{ |i| (i.industry == @industry) } unless @industry.nil?
u0sqgete

u0sqgete2#

transactions.select do |t|
  (@currency.nil? || t.currency == @currency) &&
  (@geo.nil? || t.geo == @geo)  &&
  (@industry.nil? || t.industry == @industry)
end

这个应该可以了。
或者,如果您对动力学感兴趣:

[:currency, :geo, :industry].all? do |field|
   (ivar = instance_variable_get("@#{field}")).nil? || t.send(field) == ivar
end
efzxgjgh

efzxgjgh3#

尽可能使用AR/SQL而不是Ruby处理:

transactions.where(currency: @currency, geo: @geo, industry: @industry)
gkl3eglg

gkl3eglg4#

在这种情况下,多次使用select是多余的。您可以使用&&||逻辑运算符:

transactions.select do |transaction| 
  (@currency.nil? || transaction.currency == @currency) &&
  (@geo.nil? || transaction.geo == @geo) &&
  (@industry.nil? || transaction.industry == @industry)
end

相关问题