问题描述
我试图通过实行同一型号的记录之间的多重关系自联接(基于@Shtééf's回答)。我有以下型号
I am trying to implement multiple relations between records of the same model via self-joins (based on @Shtééf's answer). I have the following models
create_table :relations, force: true do |t|
t.references :employee_a
t.string :rel_type
t.references :employee_b
end
class Relation < ActiveRecord::Base
belongs_to :employee_a, :class_name => 'Employee'
belongs_to :employee_b, :class_name => 'Employee'
end
class Employee < ActiveRecord::Base
has_many :relations, foreign_key: 'employee_a_id'
has_many :reverse_relations, class_name: 'Relation', foreign_key: 'employee_b_id'
has_many :subordinates, through: :relations, source: 'employee_b', conditions: {'relations.rel_type' => 'manager of'}
has_many :managers, through: :reverse_relations, source: 'employee_a', conditions: {'relations.rel_type' => 'manager of'}
end
通过这个设置,我可以成功访问下属和经理的名单为每个记录。然而,我有困难创建以下列方式关系
With this setup I can successfully access the lists of subordinates and managers for each record. However, I have difficulties to create relations in the following way
e = Employee.create
e.subordinates.create
e.subordinates #=> []
e.managers.create
e.managers #=> []
现在的问题是,它并没有设置关系的类型,所以我必须写
The problem is that it does not set type of relations, so I have to write
e = Employee.create
s = Employee.create
e.relations.create employee_b: s, rel_type: 'manager of'
e.subordinates #=> [#<Employee id:...>]
我是不是做错了什么?
Am I doing something wrong?
推荐答案
您可以使用 before_add
和 before_remove
回调上的has_many关联:
You can use before_add
and before_remove
callback on the has_many association :
class Employee < ActiveRecord::Base
has_many :relations, foreign_key: 'employee_a_id'
has_many :reverse_relations, class_name: 'Relation', foreign_key: 'employee_b_id'
has_many :subordinates,
through: :relations,
source: 'employee_b',
conditions: {'relations.rel_type' => 'manager of'}
:before_add => Proc.new { |employe,subordinate| employe.relations.create(employe_b: subordinate, rel_type: 'manager of') },
:before_remove => Proc.new { |employe,subordinate| employe.relations.where(employe_b: subordinate, rel_type: 'manager of').first.destroy }
has_many :managers,
through: :reverse_relations,
source: 'employee_a',
conditions: {'relations.rel_type' => 'manager of'}
:before_add => Proc.new { |employe,manager| employe.reverse_relations.create(employe_a: manager, rel_type: 'manager of') },
:before_remove => Proc.new { |employe,manager| employe.reverse_relations.where(employe_b: subordinate, rel_type: 'manager of').first.destroy }
这应该工作,使你能够使用 employe.managers.create
您可能需要使用构建
的instread创建
回调
你也可以读this这个解决的问题
This should works and make you able to use employe.managers.create
You may want to use build
instread of create
in the callback
Also you can read this question about this solution
这篇关于许多一对多多个协会自加盟的ActiveRecord的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!