在 Rails 中,我有这个 User 模型:
class User < ActiveRecord::Base
enum role: [:adult, :child, :admin]
after_initialize :set_default_role, :if => :new_record?
# belongs_to :spouse, :foreign_key => :spouse_id, :class_name => 'User', :inverse_of => :spouse
def set_default_role
self.role ||= :adult
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
def marry(user)
self.spouse = user
user.spouse = self
end
end
Run Code Online (Sandbox Code Playgroud)
我通过这次迁移添加了配偶:
class AddFieldsToUser < ActiveRecord::Migration
def change
# for marriages
add_column :users, :spouse_id, :integer, index: true
end
end
Run Code Online (Sandbox Code Playgroud)
并且效果很好(尽管我的逆函数从未起作用# belongs_to :spouse, :foreign_key => :spouse_id, :class_name => 'User', :inverse_of => :spouse
)。我现在正在尝试通过“孩子 - 父母”关系进行另一个自我加入。一个父母可以有很多孩子,一个孩子可以有(很多/两个)父母。这是我想出的迁移:
class CreateParentalRelationships < ActiveRecord::Migration
def change
create_table :parental_relationships do |t|
t.references :parent, index: true
t.references :child
end
end
end
Run Code Online (Sandbox Code Playgroud)
我将它添加到模型中:
has_many :children, :through => :parental_relationships, class_name: "User"
has_many :parents, :through => :parental_relationships, class_name: "User"
Run Code Online (Sandbox Code Playgroud)
但该关系因以下错误而无效:
[7] pry(main)> u = User.find(3)
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 3]]
=> #<User id: 3, email: ...>
[8] pry(main)> u.children
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :parental_relationships in model Us
er
[9] pry(main)> u.parent
NoMethodError: undefined method `parent' for #<User:0x5e52eb0>
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activemodel-4.1.8/lib/active_model/attribute_methods.rb:435:in
`method_missing'
[10] pry(main)> u.parents
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :parental_relationships in model Us
er
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/reflection.rb:690:in `che
ck_validity!'
[11] pry(main)> u2.children
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :parental_relationships in model Us
er
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/reflection.rb:690:in `che
ck_validity!'
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
建立父子关系需要一些麻烦。
class ParentalRelationship < ActiveRecord::Base
belongs_to :parent, class_name: 'User'
belongs_to :child, class_name: 'User'
end
Run Code Online (Sandbox Code Playgroud)
class User < ActiveRecord::Base
has_many :parent_relationships,
foreign_key: 'child_id',
class_name: 'ParentalRelationship'
has_many :child_relationships,
foreign_key: 'parent_id',
class_name: 'ParentalRelationship'
has_many :parents,
through: :parent_relationships,
class_name: 'User'
has_many :children,
through: :child_relationships,
class_name: 'User'
has_and_belongs_to_many :marriages
belongs_to :current_marriage, class_name: 'Marriage'
def marry(spouse)
marriage = Marriage.create(users: [self, spouse])
marriage.users.each { |u| u.update(current_marriage: marriage ) }
marriage
end
def spouse
return nil unless current_marriage
current_marriage
.users.where.not('marriages_users.user_id' => id).first
end
def birth(child)
child.parents << self
child.parents << spouse if spouse
end
end
Run Code Online (Sandbox Code Playgroud)
请注意,我们需要将关系设置为ParentalRelationship两次,因为我们需要告诉 rails 应该为每种类型的关系(用户是父级还是子级)查看哪个外键。
由于在现代,人们实际上可以结过几次婚,因此我们需要一个婚姻模型和一个用于 users_marriages 的连接表。
class Marriage < ActiveRecord::Base
has_and_belongs_to_many :users
validates :users, length: { minimum: 2, maximum: 2 }
end
Run Code Online (Sandbox Code Playgroud)
rails g migration CreateUsersMarriagesJoinTable users marriages
Run Code Online (Sandbox Code Playgroud)
具有规范的示例应用程序:https : //github.com/maxcal/sandbox/tree/31614819