Rails:关联模型属性的类方法范围

时间:2015-03-12 02:19:03

标签: sql ruby-on-rails activerecord

这是我以前问过的question稍微复杂一点的版本。

背景

所以我需要的是显示文章列表。一篇文章属于媒体渠道。媒体位于特定国家/地区,并以特定语言发布文章。所以数据结构如下:

  • 文章属于媒体;媒体有很多文章
  • 媒体属于国家;国家有很多媒体
  • 媒体属于语言;语言有很多媒体

现在,如果我想通过媒体过滤文章,我可以使用以下类方法(我更喜欢类作用于范围,因为我传递参数并在方法中使用条件语句):

  def self.filter_by_media(parameter)
    if parameter == "all"
      all
    else
      where(media_id: parameter)
    end
  end

问题:

如何编写一个类方法,根据其相关模型的属性Media来过滤文章?例如,我想获得一个由某个国家或几个国家的媒体发布的文章列表(当用户没有做出任何选择时,还有一个默认国家/地区)。这是我试过的:

  # parameter can be either string 'default' or an array of id’s

  def self.filter_by_country(parameter)
    if parameter == "default"
      joins(:media).where(media: [country_id: 1])
    else
      joins(:media).where(media: [country_id: parameter])
    end
  end

但这不起作用,而且我对SQL的熟悉程度不足以弄清楚如何使这项工作。你能帮忙吗?

更新

我正在尝试@ carlosramireziii的建议。我将数组更改为哈希(不知道首先使用的是什么让我使用数组),但我在Rails控制台中遇到以下错误(为避免混淆,在我的数据库中调用media agency):

  def self.filter_by_country(parameter)
    if parameter == "default"
      joins(:agency).where(agency: {country_id: 1})
    else
      joins(:agency).where(agency: {country_id: parameter})
    end
  end

in Rails console:
> Article.filter_by_country('default')

=> Article Load (1.9ms)  SELECT "articles".* FROM "articles" INNER JOIN "agencies" ON "agencies"."id" = "articles"."agency_id" WHERE "agency"."country_id" = 1
PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "agency"
LINE 1: ...ON "agencies"."id" = "articles"."agency_id" WHERE "agency"."...
                                                             ^
: SELECT "articles".* FROM "articles" INNER JOIN "agencies" ON "agencies"."id" = "articles"."agency_id" WHERE "agency"."country_id" = 1

更新2

我在上面更新部分中的错误是我没有在agency子句中复数where。部分where(agency: {country_id: 1})应该已阅读where(agencies: {country_id: 1})。这里的复数词agencies指的是正在连接的表的名称。

1 个答案:

答案 0 :(得分:2)

你非常接近,你只需要使用嵌套哈希而不是数组。

试试这个

def self.filter_by_country(parameter)
   if parameter == "default"
      joins(:media).where(media: { country_id: 1 })
   else
      joins(:media).where(media: { country_id: parameter })
   end
end