【问题标题】:Rails4 override has_many getter methodRails4 覆盖 has_many getter 方法
【发布时间】:2016-11-16 10:08:26
【问题描述】:

我有一个 Rails 4.1.7 应用程序,其中有 usersthemes

class User < ActiveRecord::Base
  has_many :themes
end

class Theme < ActiveRecord::Base
  belongs_to :user
end

现在,用户可以创建一些自己的主题(然后这些主题将其user_id 设置为用户的id),或者可以使用任何预定义的主题(将user_id 设置为null

我想做的是:以某种方式更改has_many 关联,以便当我调用@user.themes 时,这会给我带来预定义的主题以及用户的主题。

我尝试过的:

1) 定义实例方法而不是has_many 关联:

class User < ActiveRecord::Base
  def themes
    Theme.where user_id: [id, nil]
  end
end

但由于我想与用户 (includes(:themes)) 一起预先加载主题,所以这不会真正做到。

2) 使用一些作用域 (has_many :themes, -&gt; { where user_id: nil }),但它会提供类似 ... WHERE user_id = 123 AND user_id IS NULL 的 mySql 查询,它返回空。我想用 Rails5 我可以用has_many :themes, -&gt; { or.where user_id: nil } 之类的东西来做到这一点,但现在不能选择更改 Rails 版本。

【问题讨论】:

  • 我认为重写关联是一个坏主意,因为没有指定任何用户的Theme实际上属于每个用户(许多用户),它不是has_one - has_many关系。我建议使用其他方法来实现您的目标。
  • 是的,这就是我现在使用的。只是,有时急切加载它会更好......

标签: ruby-on-rails ruby-on-rails-4 overriding has-many eager-loading


【解决方案1】:

自从发布我的问题以来,我尝试了很多方法来实现我的目标。其中一个很有趣,我想值得一提:

我尝试使用unscoperewhere 取消has_many 关联的范围,它看起来像这样:

has_many :themes, -> user = self { # EDIT: `= self` can even be omitted
  u_id = user.respond_to?(:id) ? user.id : user.ids

  unscope(where: :user_id).where(user_id: [u_id, nil])
  # or the same but with other syntax:
  rewhere(user_id: [u_id, nil])
}

当我尝试@user.themes 时,它的效果很神奇,并给出了以下 mySql 行:

SELECT `themes`.* FROM `themes`
       WHERE ((`themes`.`user_id` = 123 OR `themes`.`user_id` IS NULL))

但是当我尝试急切加载它时(毕竟是我开始研究的原因),它只是拒绝取消查询范围,并给出了相同的旧 user_id = 123 AND user_id = NULL 行。

毕竟,@Ilya 的评论和this 的答案让我相信,使用has_many 进行查询是一回事,但它还有其他方面,例如分配,并为自己的缘故覆盖它可以破坏许多其他的东西。

所以我决定继续使用我的好方法,只是我给它起了一个更具体的名称以避免将来混淆:

def available_themes
  Theme.where user_id: [id, nil]
end

至于@AndreyDeineko 的回复——因为他一直拒绝回答我的问题,总是回答从未被问过的问题——我仍然不明白为什么他的方法(与我的available_themes 具有相同的结果,但使用 3额外的查询)将是一个更好的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 2014-03-17
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    相关资源
    最近更新 更多