Cla*_*law 30 activerecord ruby-on-rails
我目前正在使用Rails 2.3.9.我知道:joins在没有显式的查询中指定选项会:select自动生成任何以只读方式返回的记录.我有一个情况,我想更新记录,虽然我已经阅读了不同的方法,我想知道哪种方式是首选或"正确"的方式.
具体来说,我的情况是我有User一个带有active命名范围的以下模型,该范围与subscriptions表执行JOIN :
class User < ActiveRecord::Base
has_one :subscription
named_scope :active, :conditions => { :subscriptions => { :status => 'active' } }, :joins => :subscription
end
Run Code Online (Sandbox Code Playgroud)
当我调用时User.active.all,返回的用户记录都是只读的,因此,例如,如果我调用update_attributes!用户,ActiveRecord::ReadOnlyRecord则会引发用户记录.
通过阅读各种来源,似乎一种流行的解决方法是添加:readonly => false到查询中.但是,我想知道以下内容:
SELECT `users`.*,这似乎是安全的,那么Rails首先想要防范什么呢? 看起来Rails应该防范:select实际明确指定的情况,这与实际行为相反,所以我没有正确理解自动设置只读标志的目的:joins吗?:readonly => false.如果命名范围与其他命名范围链接,我也害怕副作用.如果我尝试在范围之外指定它(例如,通过执行User.active.scoped(:readonly => false)或User.scoped(:readonly => false).active),它似乎不起作用.我读过的另一种解决方法是将其更改:joins为:include.我理解这种行为更好,但这有什么不利之处(除了不必要的读表中的所有列subscriptions)?
最后,我还可以通过调用使用记录ID再次检索查询User.find_all_by_id(User.active.map(&:id)),但我发现这更像是一种解决方法而不是可能的解决方案,因为它会生成额外的SQL查询.
还有其他可能的解决方案吗?在这种情况下,首选解决方案是什么? 我已经阅读了之前关于此问题的StackOverflow问题中给出的答案,但它似乎没有给出具体的指导意见.
提前致谢!
Jon*_*vin 14
我相信在这种情况下习惯性和可接受性:include而不是使用:join.我认为这:join只是在罕见的特殊情况下使用,而:include非常常见.
如果您不打算更新所有活动用户,那么添加额外的命名范围或查找条件可能是明智之举,以进一步缩小您正在加载的用户的范围,这样您就不会不必要地加载额外的用户和订阅.例如...
User.active.some_further_limiting_scope(:with_an_argument)
#or
User.active.find(:all, :conditions => {:etc => 'etc'})
Run Code Online (Sandbox Code Playgroud)
如果您决定仍然想要使用:join,并且只会更新一小部分已加载的用户,那么最好在此之前重新加载您想要更新的用户.如...
readonly_users = User.active
# insert some other code that picks out a particular user to update
User.find(readonly_users[@index].id).update_attributes(:etc => 'etc')
Run Code Online (Sandbox Code Playgroud)
如果您确实需要加载所有活动用户,并且您希望坚持使用:join,并且您可能会更新大多数或所有用户,那么您想要使用ID数组重新加载它们可能是您的最佳选择.
#no need to do find_all_by_id in this case. A simple find() is sufficient.
writable_users_without_subscriptions = User.find(Users.active.map(&:id))
Run Code Online (Sandbox Code Playgroud)
我希望有所帮助.我很好奇您使用哪个选项,或者您是否找到了更适合您的方案的其他解决方案.
| 归档时间: |
|
| 查看次数: |
9270 次 |
| 最近记录: |