1

我在一个名为的模型中有这个范围activity

scope :today, where("DATE(qualify_date) = ?", Date.today)

我有另一个单独的模型 ( user) 将使用它来计算一些数字,我希望能够使用:

User.calls_for :today

然后将调用activity模型和today范围,但我无法弄清楚使用提供的符号来调用该范围

calls_for方法将包含以下内容:

activities.*scope*.to_a.sum(&:calls).to_i

4

4 回答 4

5

您将要使用 send 方法,我也相信您对 #to_a 的调用是不必要的,因为活动应该返回一个可枚举的 ActiveRelation。

def calls_for scope = :today
  activities.send(scope).sum(&:calls).to_i
end

在上述方法中,您可以只调用 User.calls_for,它与 User.calls_for(:today) 相同。这对于未来将非常灵活,因为您现在可以定义多个范围并使用相同的方法。即 call_for(:yesterday)

还要像上面显示的那样定义你的范围,这样你就不会遇到经典的陷阱。

于 2013-10-08T06:24:26.843 回答
1

活动是否属于用户?如果是这样,您可以直接调用它:

@user.activities.today

请记住,您的作用域必须是 lambda,以便它重新评估每个请求,否则它将缓存第一次调用它的日期。

# Ruby 1.8
scope :today, lambda { where("DATE(qualify_date) = ?", Date.today) }

# Ruby 1.9+
scope :today, -> { where("DATE(qualify_date) = ?", Date.today) }
于 2013-10-04T09:48:07.480 回答
1

如前所述,#send这是您想要使用的。但是您可能需要考虑使用一些元编程...我猜除了:today范围之外,您还有类似:yesterday,:two_weeks_ago等范围的东西。

因此,您始终可以执行以下操作:

def calls_for(foo)
  activities.send(foo).sum(:calls).to_i
end


def method_missing(foo, *args, &block)
  if foomatch = foo.to_s.match(/^calls_for_(\w+)/)
    foo_scope = foomatch[1].to_s
    send(:calls_for, foo_scope)
  else
    super
  end
end

def respond_to?(meth, x=false)
  if meth.match(/^calls_for_(\w+)/)
    true
  else
    super
  end
end
于 2013-10-10T15:37:52.833 回答
0

如果您想获取特殊用户的活动或所有活动的列表,我有点困惑。如果你想这样称呼它User.call_for(:today)

def self.calls_for(date)
  Activity.call(date)
end

如果你想user.call_for(:today)

def calls_for(date)
  activities.call(date)
end

但是您是否看到仅编写Activity.todayor会更容易user.activites.today

于 2013-10-04T09:53:43.003 回答