gpt4 book ai didi

ruby-on-rails - 防止 ActiveRecord::ReadOnlyRecord 的正确方法?

转载 作者:行者123 更新时间:2023-12-03 09:12:20 24 4
gpt4 key购买 nike

我目前正在使用 Rails 2.3.9。我知道指定 :joins没有明确的查询中的选项 :select自动将返回的任何记录设为只读。我有一种情况,我想更新记录,虽然我已经阅读了不同的方法来处理它,但我想知道哪种方式是首选或“正确”的方式。

具体来说,我的情况是我有以下Useractive 的模型使用 subscriptions 执行 JOIN 的命名范围 table :

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 documentation , “它们将具有与表的列不对应的属性。”但是,从此调用生成的 SQL 查询使用 SELECT `users`.*无论如何,这似乎是安全的,那么 Rails 首先要防范什么? :select 出现时,Rails 应该警惕这种情况。实际上是明确指定的,这与实际行为相反,所以我没有正确理解在 :joins 上自动设置只读标志的目的吗? ?
  • 这看起来像一个黑客吗? 命名范围的定义应该关心显式设置 :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 查询。

    还有其他可能的解决方案吗?在这种情况下,首选的解决方案是什么? 我已阅读 previous StackOverflow question about this 中给出的答案,但它似乎没有给出什么被认为是正确的具体指导。

    提前致谢!

    最佳答案

    我相信在这种情况下使用 :include 是习惯和可接受的。而不是 :join .我认为:join仅在极少数特殊情况下使用,而 :include很常见。

    如果您不打算更新所有事件用户,那么添加一个额外的命名范围或查找条件以进一步缩小您加载的用户的范围可能是明智的,这样您就不会不必要地加载额外的用户和订阅.例如...

    User.active.some_further_limiting_scope(:with_an_argument)
    #or
    User.active.find(:all, :conditions => {:etc => 'etc'})

    如果您决定仍要使用 :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')

    如果您确实需要加载所有事件用户,并且您想坚持使用 :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))

    我希望这有帮助。我很好奇您选择了哪个选项,或者您是否找到了更适合您的场景的其他解决方案。

    关于ruby-on-rails - 防止 ActiveRecord::ReadOnlyRecord 的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7667052/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com