我有一个family_tree
,有人可以将他们的亲戚添加到树中。
所以会发生的事情是为每个family_tree条目创建了membership
条记录。
但是,如果Son
添加了Dad
,我们应该能够更新爸爸的家谱,将“Son”添加到视图中的树中。什么是最好的Rails方法来解决这个问题?我知道Rails本身会做很多翻译,并且会有多元化等等。无论如何,我可以利用它来做我想做的事情吗?
另外,再次处理这些东西的类/模块是什么?的ActiveSupport?
这是我的User
型号:
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string(255) default(""), not null
# encrypted_password :string(255) default(""), not null
# reset_password_token :string(255)
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0), not null
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :string(255)
# last_sign_in_ip :string(255)
# created_at :datetime
# updated_at :datetime
# name :string(255)
# confirmation_token :string(255)
# confirmed_at :datetime
# confirmation_sent_at :datetime
# unconfirmed_email :string(255)
# invitation_relation :string(255)
# avatar :string(255)
#
class User < ActiveRecord::Base
has_one :family_tree, dependent: :destroy
has_many :memberships, dependent: :destroy
has_many :nodes, dependent: :destroy
has_many :participants, dependent: :destroy
end
FamilyTree.rb
# == Schema Information
#
# Table name: family_trees
#
# id :integer not null, primary key
# name :string(255)
# user_id :integer
# created_at :datetime
# updated_at :datetime
#
class FamilyTree < ActiveRecord::Base
belongs_to :user
has_many :memberships, dependent: :destroy
has_many :members, through: :memberships, source: :user, dependent: :destroy
has_many :nodes, dependent: :destroy
end
Membership.rb
:
# == Schema Information
#
# Table name: memberships
#
# id :integer not null, primary key
# family_tree_id :integer
# user_id :integer
# created_at :datetime
# updated_at :datetime
# relation :string(255)
#
class Membership < ActiveRecord::Base
belongs_to :family_tree
belongs_to :user
end
Node.rb
# == Schema Information
#
# Table name: nodes
#
# id :integer not null, primary key
# name :string(255)
# family_tree_id :integer
# user_id :integer
# media_id :integer
# media_type :string(255)
# created_at :datetime
# updated_at :datetime
# circa :datetime
# is_comment :boolean
#
class Node < ActiveRecord::Base
belongs_to :family_tree
belongs_to :user
belongs_to :media, polymorphic: true, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :node_comments, dependent: :destroy
end
我的_tree.html.erb
看起来像这样(为简洁而截断):
<li class="tree-item-name"><a href="#">Great Grandparents</a>
<ul>
<li><% if relative.humanize == "Great Grandfather" || relative.humanize == "Great Grandmother" %>
<%= link_to image_tag(membership.user.avatar.url, size: "48x48", :class => "img-circle") , family_tree_path(membership.user.family_tree), :target => '_blank' %>
<%= link_to membership.user.name, family_tree_path(membership.user.family_tree), :target => '_blank'%>
<% else %>
None added yet, add them <%= link_to 'here', "#" , class: 'btn invite popupbox','data-popup' => 'invite_friend' %>
<% end %>
</li>
</ul>
</li>
<li class="tree-item-name"><a href="#">Grandparents</a>
<ul>
<li><% if relative.humanize == "Grandfather" || relative.humanize == "Grandmother" %>
<%= link_to image_tag(membership.user.avatar.url, size: "48x48", :class => "img-circle") , family_tree_path(membership.user.family_tree), :target => '_blank' %>
<%= link_to membership.user.name, family_tree_path(membership.user.family_tree), :target => '_blank' %>
<% else %>
None added yet, add them <%= link_to 'here', "#" , class: 'btn invite popupbox','data-popup' => 'invite_friend' %>
<% end %>
</li>
</ul>
</li>
答案 0 :(得分:2)
我会使用你在问题中定义的相同关系,除了这一部分:
class Membership < ActiveRecord::Base
belongs_to :family_tree
belongs_to :user_one, class_name: 'User'
belongs_to :user_two, class_name: 'User' # I actually have no idea how to call them!
belongs_to :relation # to hold values likes 'Son', 'Dad', etc.
# The model Relation would be as simple as a name and internal reference, nothing else.
# (internal_reference is here to solve the translation problems and other stuff you will understand with the following code)
使用回调after_create
来撤销创建的成员资格:
def create_reverse_membership
user_one_is_female = user_one.gender == 'female'
user_two_is_female = user_two.gender == 'female'
son_or_daughter = user_one_is_female ? :daughter : :son
father_or_mother = user_two_is_female ? :mother : :father
case relation.internal_reference.to_sym
when :son
relation = Relation.find_by_internal_reference(father_or_mother)
membership = Membership.where(relation_id: relation.id, user_one: user_two.id, user_two: user_one.id).first
if membership.present?
# This means the reverse membership already exists, do not call Membership.create here because it would cause and endless loop with the callback
else
membership = Membership.create(relation_id: relation.id, user_one: user_two, user_two: user_one)
end
when :father
# almost same logic but with `son_or_daughter`
when :mother
else
end
end
英语不是我的母语,这段代码可能缺乏一致性(连贯性,逻辑性)。
希望这有帮助!