我有两个范围,我的大多数模型共享。它们具有直接引用模型表名的原始SQL,并且与Arel不能很好地匹配:
class ApplicationRecord < ActiveRecord::Base
valid = lambda do |positive = true|
if %w[validForBegin validForEnd].all? { |c| base_class.column_names.include?(c) }
condition = "NOW() BETWEEN #{base_class.table_name}.validForBegin AND #{base_class.table_name}.validForEnd"
condition = "!(#{condition})" unless positive
where(condition)
end
end
scope :valid, valid
scope :invalid, -> { valid(false) }
end
# Sample usage
class Party < ApplicationRecord
has_one :name,
-> { valid },
class_name: 'PartyName',
foreign_key: :partyId,
has_many :expired_names,
-> { invalid },
class_name: 'PartyName',
foreign_key: :partyId,
end
由于我的范围直接涉及模型table_name
,因此我无法立即加入这两种关联:
Party.joins(:name, :expired_names).first
# Produces this sequel statement
SELECT `party`.*
FROM `party`
INNER JOIN `party_name` ON `party_name`.`partyId` = `party`.`id`
AND (NOW() BETWEEN party_name.validForBegin AND party_name.validForEnd)
INNER JOIN `party_name` `expired_names_party` ON `expired_names_party`.`partyId` = `party`.`id`
AND (!(NOW() BETWEEN party_name.validForBegin AND party_name.validForEnd))
ORDER BY `party`.`id` ASC LIMIT 1
请注意,&#39; AND&#39;联接的条件是指表party_name
。第二个应该是指动态生成的表别名expired_names_party
。对于更复杂的Rails查询,其中Arel为每个表分配别名,两个连接都将失败。
我的作用域是否可以在执行时使用Arel分配给它的别名?
答案 0 :(得分:1)
我创建了这个回购来帮助测试你的情况: https://github.com/wmavis/so_rails_arel
我认为问题在于你正在尝试为两种关系使用相同的类。默认情况下,rails希望使用与该类关联的表的类名。因此,它使用表名party_name
进行查询。
为了解决这个问题,我创建了一个继承自ExpiredName
的{{1}}类,但告诉rails使用PartyName
表:
https://github.com/wmavis/so_rails_arel/blob/master/app/models/expired_name.rb
expired_names
这似乎解决了我的代码中的问题:
class ExpiredName < PartyName
self.table_name = 'expired_names'
end
如果它对您不起作用,请告诉我,我会尽力帮助。