使用Ruby 1.9.2在Mac OS X上运行Rails 3.0.7
我有三个模型,后面有表格(sqlite3表示dev,postgres表示prod)。它们如下(验证和其他不相关的行被截断):
class ServiceProvider < ActiveRecord::Base
has_many :services
has_many :advertisements, :through => :services
scope :active, where("service_providers.active = ?", true)
end
class Service < ActiveRecord::Base
belongs_to :service_provider
has_many :advertisements
scope :active, joins(:service_provider).where("services.active = ?", true) & ServiceProvider.active
end
class Advertisement < ActiveRecord::Base
belongs_to :service
scope :ranked, where("advertisements.rank > 0")
scope :current, where("start_date <= ? AND end_date >= ?", Date.today, Date.today)
scope :service_active, joins(:service) & Service.active
scope :active, ranked.current.service_active
end
如您所见,每个服务提供商都有许多服务,每个服务都可以有很多广告。广告表中包含service_id外键,services表中包含service_provider_id外键。所有相当标准的多对一关系。可以通过“活动”标志使服务提供者处于非活动状态,就像个别服务一样。
我希望能够做的是在广告模型上创建一个命名范围,以便为我提供所有广告的列表,这些广告是排名和当前以及谁的父服务是活动的,反过来谁的service_provider是活动的。换句话说,如果某个服务处于非活动状态,那么指向该服务的所有广告都将变为非活动状态,如果服务提供商变为非活动状态,则所有服务都将变为非活动状态,而这些服务下的所有广告将变为非活动状态。
我已经开始创建上面所需的命名范围,它在Service.active和ServiceProvider.active级别按预期工作,但是如果我输入Advertisement.active,我会收到错误:
ActiveRecord::ConfigurationError: Association named 'service_provider' was not found; perhaps you misspelled it?
我认为这是因为我没有将service_provider_id作为广告商表中的外键字段,但我认为我不需要它,因为它应该通过服务表上的service_provider_id字段访问service_provider。感觉我需要belongs_to:service_provider,:through =&gt; :我的广告模型中的service子句,但据我所知,这是不可能的。我已经尝试了各种各样的方法来实现这个目标,但我正在努力取得进展。
有人能告诉我一个很好的方法来实现上述目标,理想情况下不会改变我的表结构吗?我需要它非常有效,因为此查询将针对我网站上的每个页面加载运行(每页上的侧边栏广告)。
非常感谢, 克雷格。
答案 0 :(得分:7)
我认为以下内容可行:
class Advertisement
scope :service_active, joins(:service => :service_provider)
.where(:services => { :active => true })
.where(:service_providers => { :active => true })
end
然后你应该可以打电话了
Advertisement.ranked.current.service_active
并获得预期结果。