0

好的,所以我有一个范围可以找到位置等于参数的模型:

class EatTile < ActiveRecord::Base
  attr_accessible :category, :link, :map, :name, :num_votes, :position, :price, :rating

  scope :pos, lambda{|position| {:conditions => ["position = ?", position]}}
end

在我的控制器中,我有以下内容来获取我需要的瓷砖:

@tiles = EatTile.where("position > 0 AND position < 20")

我在想,如果我想获得位置为 1 的图块的名称,我可以在我的视图中调用这样的东西:

@tiles.pos(1).name

相反,我必须在 pos 调用和名称之间包含“first”。这是最好的方法吗?我是 Rails 新手,不想早早做错事。

另外,按照我上面的方式来做是否更快,或者在我看来,这样做会更好:

EatTile.pos(1).first.name

我认为我这样做的第一种方法更正确,因为它首先缩小了查询范围,但我不确定。

谢谢!

4

2 回答 2

2

您必须输入first,因为查询的结果是一个数组(一般来说)。试想一下,您可能有几条符合您的条件的记录,不从数组中检索一个对象并对其调用方法看起来很荒谬,不是吗?

关于数组。当您键入该@tiles.pos(1)行时,实际上您已经获得了ActiveRecord::Relation. 您可以通过键入来检查它@tiles.pos(1).class。拥有 Relation 对象允许我们与另一个查询链接,目的是在最后生成一个 SQL 查询到数据库。

更新:

看起来解决方案可能是这样的:

scope :pos, lambda { |position| where(:position => position).first }

但这可能会导致未来的错误,因为作用域的目的是与另一个查询链接,调用该方法first将杀死惰性功能。

我认为解决方案可能只是添加方法:

def self.get_pos(position)
  pos(position).first
end

所以你可以像这样使用它

EatTile.get_pos(1).name
于 2012-08-20T06:13:24.730 回答
2

您可以定义自定义类方法pos

class EatTile < ActiveRecord::Base
  def self.pos(position)
    where(:position => position).first
  end
end

这将使使用@tiles.pos(1).name.

于 2012-08-20T06:34:56.857 回答