【问题标题】:Neo4j.rb How to Subclass ActiveRel relationship?Neo4j.rb 如何继承 ActiveRel 关系?
【发布时间】:2017-09-07 13:39:17
【问题描述】:

新手 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_accountsaccounts 方法...

【问题讨论】:

    标签: ruby-on-rails ruby neo4j neo4j.rb


    【解决方案1】:

    亚当夏普@adamsharp 9 月 7 日 13:32 @cheerfulstoic — 一点也不耽误! ActiveRel 上的继承会像ActiveNode 上的那样,其中子类项是每个级别的 .all 的一部分。我的项目中有一些实例可以使用直接方法,但有一两个地方我需要关系中的其他属性和逻辑。

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

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

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

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

    2) 将所有逻辑重构为中间 ActiveNode 类型,即本示例中的 AccountRole,我可以将其子类化,以便将 OwnerRole

    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,但非常渴望你的选择。

    再次感谢!

    布莱恩·安德伍德 @cheerfulstoic 9 月 7 日 20:29 @adamsharp 实际上,使用 self.accounts.rel_where(role: ‘owner) 然后, owns 方法仍将返回一个代表 Account 节点的 QueryProxy,您可以进一步过滤或链接关联。您还可以在 User 上使用同名的类方法,使用 all 实现(例如 self.accounts.rel_where(role: 'owner)),这将允许您像 User.all.owns 或 Something.users.owns 等那样进行链接...

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

    布赖恩安德伍德@cheerfulstoic 9 月 7 日 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 人。这很好玩。

    【讨论】:

      【解决方案2】:

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

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

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

      真的,可能,我们应该允许rel_class: [:OwnsAccount, :ManagesAccount],我认为

      【讨论】:

      • 从 Gitter 复制/粘贴。很高兴在任何一个地方进行讨论
      • 复制我们在 Gitter 上的其余帖子,以防其他人遇到这个问题。
      猜你喜欢
      • 1970-01-01
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多