Neo4j.rb 如何继承 ActiveRel 关系?

Neo4j.rb How to Subclass ActiveRel relationship?

新手 Neo4j.rb (v8.2.1) gem 用户正在尝试弄清楚如何正确处理子类化 ActiveRel...

我有一种名为 HasAccount 的关系类型,然后我将其子类化为其他关系类型,即 OwnsAccount < HasAccount。我在我的模型中定义了这样的关系:

has_many :out, :accounts, rel_class: :HasAccount
has_many :out, :owned_accounts, rel_class: :OwnsAccount
has_many :out, :managed_accounts, rel_class: :ManagesAccount

我的意图是,每当我为节点创建 OwnsAccountManagesAccount 关系时,它们也可以通过 my_node.accounts 访问(即超类 has_many).

我是不是处理错了?我已经尝试了每一种方式,并且避免完全放弃 HasAccount 并定义一个合并 owned_accountsmanaged_accounts...

accounts 方法

不幸的是,我不认为 subclasses ActiveRel classes 会有帮助(可能你已经发现了 ;))。

如果你没有 ActiveRel class 你可以指定多种类型(我不记得我们是否实现了 type: [:OWNS_ACCOUNT, :MANAGES_ACCOUNT] 但你当然可以做任何一个 type: "OWNS_ACCOUNT|MANAGES_ACCOUNT”’type: false / type: :any).

如果你需要对你的关系有逻辑,那么你需要 ActiveRel。我想你可以在 ActiveRel class 上有 type :any,但我不知道在那种情况下你如何拥有单独的 owned_accounts / managed_accounts 关联(我认为 typerel_class 是互斥的,但它可能是工作尝试)。

真的,也许,我们应该考虑 rel_class: [:OwnsAccount, :ManagesAccount],我认为

Adam Sharp @adamsharp 9 月 7 日 13:32 @cheerfulstoic — 一点都不拖延! <24小时免费产品闪电服务!知道答案不是 "here's the stupid mistake you made." 也感觉好多了,谢谢。 是的,我曾希望 ActiveRel 上的继承会像 ActiveNode 上的那样,其中 subclassed 项目是每个级别的 .all 的一部分。我在我的项目中有一些实例可以使用直接方法,但是在一两个地方我需要关系中的其他属性和逻辑。

我还考虑了另外两种方法:

1) 只有 HasAccount 但具有角色 属性。但是我很难找出为父节点编写 owns 方法的最简单方法,类似于:

def owns
  self.accounts.(SOME LOGIC FOR role == 'owner' IN THE REL)
end

也不确定如何在设置后更改角色,并且想知道性能方面的单独 rels 是否会更好。

2) 将所有逻辑重构为中间 ActiveNode 类型,即本例中的 AccountRole ,我可以将其子class 以便 OwnerRole < AccountRole 节点将包含在任一范围内。那么我的模型的关键部分是:

class AccountRole
  include Neo4j::ActiveRel

  from_class :User
  to_class   :Account

  def account
    self.to_node
  end
end

class OwnerRole < AccountRole

end

class User

  include Neo4j::ActiveNode
  include Neo4j::Timestamps

  has_many :out, :has_account_roles, rel_class: :AccountRole
  has_many :out, :has_owner_roles, rel_class: :OwnerRole

  def accounts
    self.has_account_roles.map{ |role| role.account }
  end

  def owns
    self. has_owner_role.map{ |role| role.account }
  end

end

现在倾向于 #2,但非常期待您的选择。

再次感谢!

Brian Underwood @cheerfulstoic 9 月 07 20:29 @adamsharp 实际上,用 self.accounts.rel_where(role: ‘owner) 之类的东西做 #1 应该很容易 然后 owns 方法仍然 return 一个 QueryProxy 表示您可以进一步过滤或链接关联的帐户节点。您还可以在 User 上使用相同名称的 class 方法实现所有(例如 self.accounts.rel_where(role: 'owner)),这将允许您像 User.all.owns 或 Something.users.owns, 等...

Adam Sharp @adamsharp 9 月 7 日 21:44 惊人的。谢谢@cheerfulstoic!会试一试。更改 rel 属性 最简单的方法是什么? (即从所有者到经理)?

Brian Underwood @cheerfulstoic 9 月 07 21:57 如果你有一个 ActiveRel 对象,你可以说 rel.role = ‘owner’; rel.save / rel.update(角色:‘所有者’)。否则,您将使用 Cypher 或 Ruby API,例如 user.owns(:node, :rel).where(id: account.id).query.set(rel: {role: ' owner'}).exec(显然这更冗长,但如果您要更新多个,该语法会很有用)

亚当夏普@adamsharp 13:48 谢谢@cheerfulstoic。是的,它试图构建后者,并通常找出访问相关对象的简洁方法,这让我在这方面陷入了困境。会走这条路。谢谢您的帮助!我的整个职业生涯都是 SQL 人。这好有趣。