【发布时间】:2015-12-22 13:12:25
【问题描述】:
背景
我有五个模型:Reward、BrandSubscription、Brand、Tier 和 User。
-
Brand有很多Tiers。 -
BrandSubscription属于Tier和User。 -
Reward属于Tier。 -
Tier有一个名为order的属性。如果BrandSubscription具有更高的层级,则它也将具有所有较低的层级。 - 一个
BrandSubscription可以从它的所有Tiers中看到所有Rewards,在这种情况下是它所属的Tier及其所有较低的Tiers。
问题
我的问题是上面列表的最后一项。我正在尝试获得品牌订阅的所有奖励。
理想的方式是BrandSubscription 实体上的has_many :rewards,即through: :tier。在Tier 我可以有一个has_many :rewards。这种方法的问题是奖励不限于当前层,而是必须包括来自较低order层的所有奖励。
为了实现这一点,我在Tier 模型的has_many :rewards 上设置了一个范围:
class Tier < ActiveRecord::Base
belongs_to :brand
has_many :rewards
has_many :with_lower_tiers, lambda {
where(this_table[:order].gteq(that_table[:order]))
}, through: :brand, source: :tiers
has_many :achievable_rewards, through: :with_lower_tiers, source: rewards
end
这里的问题在于this_table 和that_table。我需要在这里进行某种连接,这样我就可以在表格之间进行比较。我可以采用的一种方法是:
class Tier < ActiveRecord::Base
belongs_to :brand
has_many :rewards
has_many :with_lower_tiers, lambda { |tier|
where(current_scope.table[:order].lteq(tier.order))
}, through: :brand, source: :tiers
has_many :achievable_rewards, through: :with_lower_tiers, source: rewards
end
这里我使用层所有者对象并获取它的顺序。这里的问题是我不能真正依赖tier 参数。以下查询已经中断,因为真正作为参数传递给范围函数的是查询的“所有者”实体,在本例中为BrandSubscription:
BrandSubscription.joins(:with_lower_tiers)
我想要获得的 SQL 查询如下,我可以从用户那里获得所有可用的奖励。请注意,我加入了 tiers 表两次,而这正是我遇到麻烦的地方:
SELECT DISTINCT rewards.*
FROM tiers
INNER JOIN brand_subscriptions ON tiers.id = brand_subscriptions.tier_id
INNER JOIN tiers tiers_reward ON tiers_reward.brand_id = tiers.brand_id
INNER JOIN rewards ON tiers_reward.id = rewards.tier_id
WHERE tiers_reward.order <= tiers.order
AND brand_subscriptions.user_id = 1234
我相信一些 Arel 可能会有所帮助,但如果我可以完全依赖 ActiveRecord 来完成这项工作,我真的很高兴,因为代码会更简洁。
参考
我正在使用以下链接来尝试解决此问题:
- Join the same table twice with conditions
- https://robots.thoughtbot.com/using-arel-to-compose-sql-queries
- http://jpospisil.com/2014/06/16/the-definitive-guide-to-arel-the-sql-manager-for-ruby.html
- https://gist.github.com/mildmojo/3724189
- http://jpospisil.com/2014/06/16/the-definitive-guide-to-arel-the-sql-manager-for-ruby.html
- ActiveRecord query with alias'd table names
【问题讨论】:
标签: mysql ruby-on-rails ruby activerecord arel