我目前正在使用Rails 2.3.9版本。我知道在查询中指定
具体而言,我的情况是我有以下
当我调用
提前感谢!
:joins
选项但没有明确的:select
会自动使返回的任何记录只读。我有一个需要更新记录的情况,虽然我已经阅读了不同的方法来解决它,但我想知道哪种方式是首选或"正确"的方式。具体而言,我的情况是我有以下
User
模型,其中active
命名范围执行与subscriptions
表的连接:class User < ActiveRecord::Base
has_one :subscription
named_scope :active, :conditions => { :subscriptions => { :status => 'active' } }, :joins => :subscription
end
当我调用
User.active.all
时,返回的用户记录都是只读的,因此,如果我在用户上调用update_attributes!
,将会引发ActiveRecord::ReadOnlyRecord
异常。通过阅读各种来源,似乎一个流行的解决方法是在查询中添加:readonly => false
。但是,我想知道以下内容:
- 这是安全的吗? 我理解Rails最初将其设置为只读的原因是因为根据Rails文档,“它们将具有不对应于表列的属性。” 但是,从此调用生成的SQL查询仍然使用
SELECT `users`.*
,这似乎是安全的,所以Rails试图在第一次防范什么? 看起来Rails应该防范的是实际上明确指定:select
时的情况,这与实际行为相反,所以我是否没有正确理解自动设置:joins
的只读标志的目的? - 这看起来像一个hack吗? 命名范围的定义关心显式设置
:readonly => false
似乎不合适。 我也担心命名范围与其他命名范围链接时会产生副作用。 如果我尝试在范围之外指定它(例如通过执行User.active.scoped(:readonly => false)
或User.scoped(:readonly => false).active
),它似乎不起作用。
我读到的另一种解决方法是将:joins
更改为:include
。 我更好地理解了这种行为,但是是否有任何缺点(除了不必要地读取subscriptions
表中的所有列)?
User.find_all_by_id(User.active.map(&:id))
再次使用记录ID来检索查询,但我认为这更像是一种解决方法而不是可能的解决方案,因为它会生成额外的SQL查询。
还有其他可能的解决方案吗?在这种情况下,什么是首选解决方案?我已经阅读了关于此的上一个StackOverflow问题中给出的答案,但似乎没有给出具体的指导来说明什么是正确的。提前感谢!
ActiveRecord::ReadOnlyRecord
问题的具体指导。其他问题主要是为了让我理解为什么一个特定的解决方案比另一个更好。 - Claw