【问题标题】:Boolean field indicating that record has belonging association with given field value指示记录与给定字段值具有关联的布尔字段
【发布时间】:2015-06-09 10:46:36
【问题描述】:

我的模特:

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)

这是我不完整的解决方案(如果我尝试对结果执行 .count,则会引发 ActiveRecord::StatementInvalid: SQLite3::SQLException):

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

【问题讨论】:

  • 我不明白你想从这个查询中得到什么结果?
  • @Fenec 我的错。更新了预期行为的问题

标签: ruby-on-rails ruby sqlite activerecord rails-activerecord


【解决方案1】:

其实这里的问题很简单。如果您查看完整的错误:

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

注意到上面出现的#&lt;User:0x007fcb357a5ed8&gt;?这是因为在 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

【讨论】:

  • 对不起。这是示例中的错误输入
  • 这绝不是一个解决方案,应该删除
  • @IvanDenisov 然后改变你的问题,因为现在它是唯一适用于你所描述的东西。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 2016-06-26
  • 2019-01-26
  • 2016-03-20
  • 2021-04-06
  • 1970-01-01
相关资源
最近更新 更多