【问题标题】:Union of two scopes results in NoMethodError (undefined method `default_scoped?' ...)两个范围的联合导致 NoMethodError(未定义的方法 `default_scoped?' ...)
【发布时间】:2012-01-18 12:30:00
【问题描述】:

我已经定义了以下两个范围,并且都可以正常工作:

scope :regular_friends, lambda { |user| joins{friendships}.where{friendships.user_id.not_in(user)}}
scope :inverse_friends, lambda { |user| joins{inverse_friendships}.where{inverse_friendships.friend_id.not_in(user)}}

我在这里使用 squeel (https://github.com/ernie/squeel) 并建立一个自引用关联,其灵感来自 (http://railscasts.com/episodes/163-self-referential-association) .

基于此,我想定义第三个作用域,它将其他两个的结果联合起来:

scope :friends, lambda { |user| User.regular_friends(user).union(User.inverse_friends(user)) }

不幸的是,它不起作用。我得到一个:

NoMethodError (undefined method `default_scoped?' for #<Arel::Nodes::Union:0x8249534>):

我使用的是 Rails 3.1.3。我认为 default_scope? 方法已在 Rails 3.* 中删除,但它抱怨...

谁能帮忙?

【问题讨论】:

    标签: ruby-on-rails-3 ruby-on-rails-3.1


    【解决方案1】:

    Rails 中没有 union 这样的方法(我不知道 Arel)。只需像往常一样构建作用域即可。

    编辑: 您始终可以在范围定义中使用原始 sql。我不知道您的应用程序的详细信息(尤其是表是如何互连的),因此我无法构建完整的查询。不过,查询看起来与此类似:

    scope :friends, find_by_sql(%(
      SELECT users.* FROM users INNER JOIN friendships f on f.user_id = users.#{id} WHERE ...
      UNION
      SELECT users.* FROM users INNER JOIN inverse_friendships i on i.friend_id = users.#{id} WHERE ...
    )
    

    【讨论】:

    • Arel 提供了一个 Arel::Nodes:Union 并找到了一些使用 union() 方法的示例,所以我猜有一个。无论如何,我不确定如何设计朋友范围以正常方式返回其他范围的联合。
    • 您始终可以在范围定义中使用原始 sql(我想如果您想要联合的话,这将是一种方式)
    【解决方案2】:

    default_scope? 确实已从 Rails 3 及更高版本中删除。 我不知道为什么会弹出这个错误(我有同样的问题),但在作用域中使用union() 似乎不起作用。直接使用它们(在scope 之外)似乎有效:

    User.regular_friends(user).union(User.inverse_friends(user))
    

    就我个人而言,我不会将联合放在一个范围内并直接使用它(幸运的是我只在一个地方使用它,所以对我来说这没什么大不了的)。

    我也不能直接将union()find()first()all()等一起使用。我猜arel还没有完成......为了规避这个问题我使用:

    sql = User.regular_friends(user).union(User.inverse_friends(user)).to_sql
    result = find_by_sql(sql)
    

    但也许/可能有更好的方法来防止这种情况......? (就像等待 arel 更新:P)

    【讨论】:

    • 需要注意的是,这个 issue 从 2012 年开始在 Arel 开放,并且仍然开放。我不希望很快得到修复。
    • 可能是github.com/brianhempel/active_record_union gem 帮助,它定义了ActiveRecord::Query 上的union 以返回ActiveRecord::Query
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多