gpt4 book ai didi

ruby-on-rails - 使用 `tap` 构建 Rails 作用域

转载 作者:数据小太阳 更新时间:2023-10-29 07:24:48 24 4
gpt4 key购买 nike

我有一个看起来像的方法

class Student < ActiveRecord::Base
def self.search(options = {})
all.tap do |s|
s.where(first_name: options[:query]) if options[:query]
s.where(graduated: options[:graduated]) if options[:graduated]

# etc there are many more things that can be filtered on...
end
end
end

虽然调用此方法时,我得到的是所有结果,而不是我期望的过滤集。我的 tap 功能似乎没有像我预期的那样工作。执行此操作的正确方法是什么(不将 all 分配给变量。如果可能的话,我想在这里使用 block )。

最佳答案

tap 对此不起作用。

  • all 是一个 ActiveRecord::Relation,一个等待发生的查询。
  • all.where(...) 返回一个 new ActiveRecord::Relation 新查询。
  • 但是检查 documentation对于 tap,您会看到它返回调用它的对象(在本例中为 all),而不是 block 的返回值。

    即它是这样定义的:

    def tap
    yield self # return from block **discarded**
    self
    end

    当你想要的只是:

    def apply
    yield self # return from block **returned**
    end

    或类似的东西。

这就是为什么您总是获取所有 返回的对象,而不是查询产生的对象。我的建议是建立发送到 where 的散列,而不是链接 where 调用。像这样:

query = {}
query[:first_name] = options[:query] if options[:query]
query[:graduated] = options[:graduated] if options[:graduated]
# ... etc.

all.where(query)

或者一个可能更好的实现:

all.where({
first_name: options[:query],
graduated: options[:graduated],
}.delete_if { |_, v| v.empty? })

(如果中间变量不合您的口味。)

关于ruby-on-rails - 使用 `tap` 构建 Rails 作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21287144/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com