2014-10-18 3 views
1

Я пытаюсь переопределить метод setter одной объявленной связи для выполнения пользовательского поведения и некоторой проверки на старом узле и новом узле.Связь и метод setter

Для примера возьмем следующий пример:

class FantasticTeam 
    include Neo4j::ActiveNode 

    has_one :in, :active, model_class: Whatever 
    has_many :in, :not_active, model_class: Whatever 

    def active=(whatever) 
    # return if whatever is not include in :not_active 
    # add the old value to :not_active 
    # delete the relationship :not_active that belongs to whatever (the param) 
    # add :active relationship to whatever 
    end 
end 

Что такое правильный способ сделать что-то вроде этого?

ответ

3

Есть два способа справиться с этим, и проще, чем переопределить метод сеттера.

Первое - использовать обратные вызовы в вашей модели ActiveNode.

class FantasticTeam 
    include Neo4j::ActiveNode 

    has_one :in, :active, before: :before_callback, model_class: Whatever 
    has_many :in, :not_active, model_class: Whatever 

    private 

    def before_callback(other) 
    return false unless self.not_active.include?(other) 
    self.not_active(:w, :r).where(uuid: other.uuid).pluck(:r).each { |r| r.destroy } 
    self.not_active << other unless self.active.nil? 
    end 
end 

Я лично никогда не использую этот процесс. Я всегда использую модели ActiveRel для любой логики отношений.

class FantasticTeam 
    include Neo4j::ActiveNode 

    has_one :in, :active, model_class: 'Whatever', rel_class: 'FantasticActiveWhatever' 
    has_many :in, :not_active, model_class: 'Whatever' 

end 

class FantasticActiveWhatever 
    include Neo4j::ActiveRel 
    from_class FantasticTeam 
    to_class Whatever 
    type 'ACTIVE' 

    validate  :inactive 
    before_create :clear_inactive 

    private 

    def inactive 
    self.errors.add(:inactive, 'Destination node must be declared inactive') unless from_node.not_active.include?(to_node) 
    end 

    def clear_inactive 
    from_node.not_active(:w, :r).where(uuid: to_node.uuid).pluck(:r).each { |r| r.destroy } 
    end 
end 

Тогда вы бы создать что:

отн = FantasticActiveWhatever.new (from_node: команды, to_node: что угодно) если rel.save # шаг на конце

ActiveRel требует некоторых дополнительная настройка, но она намного мощнее.

В любом случае, это то, что нужно обернуть в транзакцию, потому что существует потенциал для удаления отношения not_active, но не может установить active.

begin 
    tx = Neo4j::Transaction.new 
    # the whole process 
rescue StandardError 
    tx.failure 
    # additional failure behavior, if any 
ensure 
    tx.close 
end 

Основные обратные отношения оформляются в https://github.com/neo4jrb/neo4j/wiki/Neo4j-v3-Declared-Relationships#relationship-callbacks.

ActiveRel задокументирован в https://github.com/neo4jrb/neo4j/wiki/Neo4j%3A%3AActiveRel.

Сделки задокументированы по адресу https://github.com/neo4jrb/neo4j/wiki/Transaction.

+1

Еще одна вещь: 'from_node.not_active (: w,: r) .where (uuid: to_node.uuid) .pluck (: r) .each {| r | r.destroy} 'Здесь, в чем смысл: w и почему вам нужно объявить его, если вы не собираетесь его использовать? Спасибо Крису за то, что он был настоящим. – tehAnswer

+2

Это всегда 'query_start_node.association (: node_id,: rel_id)'. Если вы хотите работать с отношениями в объекте QueryProxy, вы всегда должны сначала установить идентификатор узла. – subvertallchris