我的模特:
class CountryVisit < ActiveRecord::Base
belongs_to :country
belongs_to :user
validates :country, uniqueness: { scope: user, message: 'already visited' }
end
class User < ActiveRecord::Base
has_many :country_visits
...
end
class Country < ActiveRecord::Base
has_many :country_visits
...
end
我希望每个国家/地区都有一个虚拟属性,表明它对给定用户
有country_visit
Country.for(user)
这是我不完整的解决方案(如果我尝试对结果执行ActiveRecord::StatementInvalid: SQLite3::SQLException
,则会引发.count
):
def self.for(user_id)
Country
.select("countries.*, country_visits.id AS visited")
.joins(
"LEFT OUTER JOIN country_visits ON
country_visits.country_id = countries.code
AND country_visits.user_id = #{user_id}"
)
end
预期行为:
user = User.create
#with country visit
c1 = Country.create
cv1 = CountryVisit.create(country: c1, user: user)
#without country visit
c2 = Country.create
结果应该是:
countries = Country.for(user_id).order('created_at asc')
countries.first.visited # => true
countries.last.visited # => false
答案 0 :(得分:0)
实际上这里的问题非常简单。如果你看一下完整的错误:
ActiveRecord::StatementInvalid: SQLite3::SQLException: unrecognized token:
"#": SELECT countries.*, country_visits.id AS visited FROM "countries" LEFT
OUTER JOIN country_visits ON country_visits.country_id = countries.id AND
country_visits.user_id = #<User:0x007fcb357a5ed8> ORDER BY created_at asc
请注意上面显示的#<User:0x007fcb357a5ed8>
?这是因为在for
方法中您传递的是完整的用户对象,而不是用户ID。而且由于您正在编写原始SQL,因此活动记录不足以将AR对象强制转换为ID。
解决此问题的最简单方法是将您的国家/地区方法更改为:
def self.for(user) # <-- user
Country
.select("countries.*, country_visits.id AS visited")
.joins(
"LEFT OUTER JOIN country_visits ON
country_visits.country_id = countries.code
AND country_visits.user_id = #{user.id}" # <-- user.id
)
end