传递符号作为方法?

时间:2013-10-04 09:30:17

标签: ruby-on-rails ruby

我在名为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 个答案:

答案 0 :(得分: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)相同。这对未来非常灵活,因为您现在可以定义多个范围并使用相同的方法。即calls_for(:昨天)

还可以像Matt上面所示定义你的范围,这样你就不会遇到经典的问题。

答案 1 :(得分: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) }

答案 2 :(得分: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

答案 3 :(得分: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.todayuser.activites.today会更容易。