在rails中,我有这个用户模型:
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
我通过此迁移添加了配偶:
class AddFieldsToUser < ActiveRecord::Migration
def change
# for marriages
add_column :users, :spouse_id, :integer, index: true
end
end
并且工作正常(虽然我的函数的反函数从未起作用# 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
我把它添加到模型中:
has_many :children, :through => :parental_relationships, class_name: "User"
has_many :parents, :through => :parental_relationships, class_name: "User"
但该关系不适用于以下错误:
[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!'
我错过了什么?
答案 0 :(得分:4)
设置父子关系需要进行一些调查。
class ParentalRelationship < ActiveRecord::Base
belongs_to :parent, class_name: 'User'
belongs_to :child, class_name: 'User'
end
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
请注意,我们需要设置两次与ParentalRelationship
的关系,因为我们需要告诉rails它应该为每种类型的关系(用户是父级或子级)查看哪个外键。
因为在这些近代人们实际上可以多次结婚,我们需要一个婚姻模型和一个用户联盟的联接表。
class Marriage < ActiveRecord::Base
has_and_belongs_to_many :users
validates :users, length: { minimum: 2, maximum: 2 }
end
rails g migration CreateUsersMarriagesJoinTable users marriages
答案 1 :(得分:1)
我想出了一个解决方案。不确定它是否是最好的:
我的新用户模型:
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
has_many :parental_relationships
has_many :children, :through => :parental_relationships, class_name: 'User'
has_many :parents, :through => :parental_relationships, class_name: 'User'
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
def birth(user)
self.children << user
user.parents << self
if self.spouse
self.spouse.children << user
user.parents << self.spouse
end
end
end
我必须编辑一些迁移和模型。
ParentalRelationships迁移
class CreateParentalRelationships < ActiveRecord::Migration
def change
create_table :parental_relationships do |t|
t.references :user, index: true
t.references :child
t.references :parent
end
end
end
ParentalRelationship模型:
class ParentalRelationship < ActiveRecord::Base
belongs_to :user
# , :class_name => "User"
# belongs_to :parent, :class_name => "User"
belongs_to :child, :class_name => "User"
belongs_to :parent, :class_name => "User"
end
所以,添加关系:
u = User.find(50)
u.birth(User.find(60))