Rails Active Record指定关系模型的位置

时间:2014-12-19 17:54:17

标签: ruby-on-rails activerecord

如果我有这种关系:

Foo has_many :bars

Bar belongs_to :foo

我想在Foo模型中指定一个范围,因为我想要过滤一些字段(即where("code='AV1' OR code='AH5'"

bars中包含Foo的外键。如何指定适合上述过滤器的bars?像Bar.foo.customScope之类的东西,让我们说我想过滤Bar中的某些东西?

Bar.where(".....").foo.customScope

修改

是的,代码是foo表中的一个字段

我在bars表中有几百个条目。它们中的每一个都有foos表(模型Foo)的外键。我想从bars表中获取具有特定code的所有foos的列表。 E.g。

foos:
id, code
1,okay
2,not okay
3,somewhat okay

bars:
id,foo_id,otherstuff
1,1,blah
2,1,blob
3,2,hello
4,3,hurray

如果我的Foo模型如下:

class Foo < ActiveRecord::Base
   has_many :bars

   def self.goodCodes
     where("code='okay' or code='somewhat okay')
   end

end

我的Bar模型如下所示:

class Bar < ActiveRcord::Base
  belongs_to :foo
end

我想调用一些东西来获取符合条件的所有Bar项以及满足foos条件的goodCodes项。我认为它会是这样的:Bar.where(....).foo.goodCodes或者

Bar.where(...).each do |row|
  if row.foo.goodCodes
    ##do something
  end
end

1 个答案:

答案 0 :(得分:1)

一定有些困惑。由于Bar属于1且仅{1} foo,因此运行@bar.foo只会返回1个结果:foo您已分配给@bar。范围用于返回多个记录。

如果您拥有Foo模型中提到的范围:

class Foo < ActiveRecord::Base
  scope :customScope, -> { where("code='AV1' OR code='AH5'") }
end

然后customScope范围是Foo类的一个类方法:

Foo.customScope # e.g. => [#<Foo code='AV1'], ...]

但是如果范围在Bar类:

class Bar < ActiveRecord::Base
  scope :customScope, -> { where("code='AV1' OR code='AH5'") }
end

然后拨打Bar.customScope并返回符合该条件的所有bars。您也可以将其调用以获取Foo bars的子集:

foo = Foo.new
foo.bars << Bar.new(code: 'AV1')
foo.bars << Bar.new(code: 'XXX')

foo.bars # => [#<Bar code: 'AV1'>, #<Bar code: 'XXX'>]
foo.bars.customScope # => [#<Bar code: 'AV1'>]

当你说:

时,要澄清任何困惑
  

我想在Foo模型中指定一个范围,因为有一些范围   我希望过滤的字段(即where(&#34; code =&#39; AV1&#39; OR)   代码=&#39; AH5&#39;&#34)

我认为codeFoo中的字段。但后来你说:

  

如何指定适合上述过滤器的条形图?

嗯,你不能。如果code字段位于Foo表中,则该过滤器只能用于Foo模型。您无法通过其他数据库表中的字段过滤Bar。但是,您可以获取与过滤器或范围Foo匹配的所有Foo.customScope,然后获取所有foo s bar s:

Foo.customScope.flat_map &:bars

此外,没有这样的方法Bar.fooBar是一个类,只有Bar的实例才会回复foo

Bar.foo # NoMethodError
bar = Bar.new
bar.foo = Foo.new
bar.foo # the new foo

更新:

这不会起作用:

row.foo.goodCodes

因为goodCodes是Foo上的类方法,而不是row.foo等实例。就像我上面说的那样,你需要这样做:

Foo.customScope.flat_map &:bars

获取bar匹配条件的所有foo

原因是当您获得Bar的实例时,例如:

Bar.where(...).each do |row|
  if row.foo.goodCodes
    ##do something
  end
end

row现在是Bar的实例row.foo将返回foo实例您无法在实例上调用范围或类方法 。这不会起作用:row.foo.goodCodes,因为您将goodCodes定义为Foo的类方法。如前所述,您可以致电:

foos_with_good_codes = Foo.goodCodes
bars_with_foos_that_have_good_codes = foos_with_good_codes.flat_map &:bars

希望能稍微清理一下。