哪里放置返回集合的方法

时间:2015-03-02 18:27:02

标签: ruby-on-rails ruby

我有一个商店模型。

在我的课堂上,我创建了几种方法,使我能够更容易地阅读代码。

类似的事情:

# Returns True if the shop has an owner
def is_claimed
  return self.owner_id != nil
end

现在我想创建一个返回商店集合的方法。

类似的东西:

def get_all_open
  return Shop.where("shops.closed != 1")
end

我只是想知道应该放在哪里,所以我可以在任何可以使用的地方使用

Shop.all

在我的代码中。

  • 如果我将它放在模型中,它将可用于商店的实例,这听起来很奇怪。
  • 此方法也属于商店,因此我不太喜欢将其放在 ApplicationController 中。
  • 我还想过将它放在shops_controller中,但是它很难轻易地提供给其他控制器。

我在互联网上看过,但到目前为止找不到我喜欢的东西。什么被认为是铁路的良好做法?

由于

3 个答案:

答案 0 :(得分:3)

您可以将其保留在模型中,但不要将其定义为实例方法,而是将其定义为类方法:

def self.all_open
  where("shops.closed != 1")
end

这样你可以像这样使用它:

Shop.all_open

甚至嵌套方法,如下:

Shop.all_open.where(field: "value")

<强>更新

与其他人指出的一样,您也可以使用范围(这是首选方式):

class Shop < ActiveRecord::Base
  scope :all_open, -> { where("shops.closed != 1") }
end

用法是相同的:

Shop.all_open

答案 1 :(得分:2)

这是Scopes通常用于的目的。

class Shop < ActiveRecord::Base
  scope :open, ->{ where("shops.closed != 1") }
  #            ->{ where.not(closed: true) } # <- Either will work, but I prefer this

  # ...
end

然后:

Shop.open.all # => (a collection of Shops)

范围的优势在于您可以将它们链接起来,因此,例如,如果您的Shop模型具有type属性,您可以获得具有特定type的所有打开的商店,如下所示:< / p>

Shop.open.where(type: "pharmacy").all

答案 2 :(得分:0)

在Shop中将其定义为类方法。

class Shop
  def self.all_open
    where("shops.closed != 1")
  end
end

open_shops = Shop.all_open

注意:

0)self中的def self.all_open使得这个类方法在类本身上定义,并且可以在类本身上调用为Shop.all_open,而不是普通实例需要在特定实例上调用的方法。

1)当您致电all_open时,调用方法get_all_open而不是Shop.all_open会产生更自然和惯用的代码。实际上,我可以将其称为open,导致open_shops = Shop.open

2)注意建议的实现省略了return,只是为了便于阅读。请注意,它也会忽略Shop.where,而只会忽略where。这主要是因为你最终制作商店的子类,你可能不会,但是风格好,代码更短。只有whereself.where相同,因为这是一个类方法,self是类本身Shop(除非您有继承此代码的子类,在这种情况下self可以是一个子类)。

3)事实上你可以把它与东西连在一起,没问题。看看:Shop.all_open.where(:city => "Baltimore").order(:updated_at)。非常整洁,它只是有效!

4)有些人会告诉你使用ActiveRecord'范围'。你真的不需要这种情况,你可以写一个简单的旧方法,就像那样。 Rails docs承认有关使用范围进行此类事情:“这与定义类方法完全相同,而您使用的是个人偏好问题。”我只是在这里使用一个简单的旧方法,就像你开始一样(除了在模型上定义为类方法) - 它更直接,它做你期望的,你不需要了解'范围',这只是一种方法。使用范围来代替这种方式是在Rails以这种方式使用普通类方法支持之前的一种遗留问题,普通的类方法就好了。