【问题标题】:How to make chainable methods (scopes) with conditions not tied to database如何使用与数据库无关的条件创建可链接的方法(范围)
【发布时间】:2011-09-07 17:51:51
【问题描述】:

我有一个模型Item,它与自身有关系。

class Item < ActiveRecord::Base
  has_many :subitems, :class_name => "Item", :foreign_key => "superitem_id"
  belongs_to :superitem, :class_name => "Item"
end

我想查询所有有父项的项目。首先,我尝试检查 parent_id 是否存在Item.where("superitem_id != ?", false),或类似的东西。但它不起作用。尽管该项目具有 superitem_id,但 superitem 可能已经被销毁。所以我必须用类方法来做

def self.with_superitems
  items = []
  self.find_each do |i|
    items << i if i.superitem
  end
  return items
end

但它使链接成为不可能,我想用类似的方法链接它,比如

def self.can_be_stored
  items = []
  self.find_each do |i|
    items << i if i.can_be_stored?
  end
  return items
end

是否可以使用范围实现相同的结果? 或者你会怎么做?

【问题讨论】:

    标签: ruby-on-rails activerecord scopes


    【解决方案1】:

    我过去也遇到过类似的问题。有时很难绕过它。为了我的目的,我找到了一种 hack-ish 方式,所以希望这会有所帮助......

     ids = []
     self.find_each do |i|
        ids << i.id if i.superitem
     end
    Model.where('id in (?)', ids)
    

    【讨论】:

    • 谢谢!好像可行 =) 顺便说一句,我还不太了解,但是您的 items.inject([]){|a,b| a+=[b.id]} 可以替换为 items.map(&amp;:id)
    • 谢谢,反正我已经整理了一下,所以它不需要循环遍历列表两次
    • 不。它不连锁。 Item.countable.occupied # []Item.countable.occupied.to_sql # "SELECT \"items\".* FROM \"items\" WHERE (id in (10,40)) AND (id in (NULL)) ORDER BY name asc"。它希望它会像(Item.countable &amp; Item.occupied) # [#&lt;Item id: 40, name: "abs"&gt;](Item.countable &amp; Item.occupied).to_sql # "SELECT \"items\".* FROM \"items\" WHERE (id in (10,40)) AND (id in (18,40,45)) ORDER BY name asc"
    【解决方案2】:

    在 Rails 2 中我会这样做

    items = Item.find(:all, :include => [:superitems], :conditions => ["superitems.id is not null"])
    

    rails3 等价于

    Item.includes([:superitem]).where("superitems.id is not null").all
    

    通过这种方式,您将拉入父项并测试联接超项侧的 id 字段是否具有 id。如果没有,那是因为那里没有超项(或者,从技术上讲,它可能存在但没有 id。但这通常不会发生)。

    【讨论】:

    • 它不起作用。我认为这是因为没有 superitem 表(项目与自身作为超项目相关)。 ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: superitems.id
    • 好吧。我认为我的帖子中实际上存在三个问题。 1)是否可以制作可链接的类方法。 2) 如何使用 sql 查询仅提取具有父级的实例。 3)在自我关系的情况下如何做到这一点。你肯定回答了第二个。所以谢谢你=)
    • 啊,是的,忘了它是自我参照的,抱歉。我认为 :dependent => :nullify 无论如何都是要走的路:)
    【解决方案3】:

    以下将获取所有带有父项的项目,当您说“虽然该项目具有 superitem_id,superitem 可能已经被销毁”时,我不确定您的意思

    items = Item.where("superitem_id IS NOT NULL")
    

    【讨论】:

    • 我的意思是,当我摧毁超级物品时。项目仍有 superitem_id。 @item.superitem_id # 输出 31 Item.find(31).destroy @item.superitem_id # 仍然输出 31 这意味着,没有 superitem,所以你的 Item.where("superitem_id IS NOT NULL") 不会得到所有带有父项的项目,而只是所有带有 superitem_id 的项目
    • @ilzoff 在删除一个项目之前,为什么不遍历它的所有子项并删除 superitem_id?这样你就没有任何多余的数据,而且你可以保持干净和简单?
    • 是的。我一定会这样做的。尤其是现在,因为我找到了:dependent =&gt; :nullify =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-16
    • 2017-03-14
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 2020-12-17
    相关资源
    最近更新 更多