2014-10-09 12 views
9

Mam i ktoś może dodać swoich krewnych do drzewa.Jak elegancko obsługiwać dwustronne relacje z tłumaczeniami Rails?

Co się dzieje, jeśli dla każdego wpisu family_tree utworzono rekord membership.

Jednak jeśli Son dodaje Dad, powinniśmy być w stanie zaktualizować drzewo genealogiczne taty, aby dodać "syna" do drzewa w widoku. Jaka jest najlepsza metoda Railsów do podejścia do tego? Wiem, że Rails wykonuje wiele tłumaczeń natywnie, i pluralizacje itp. W każdym razie, żeby wykorzystać to do tego, co chcę zrobić?

Co to jest klasa/moduł, który ponownie obsługuje te rzeczy? ActiveSupport?

To mój User model:

# == 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 

My _tree.html.erb wygląda następująco (obcięty dla zwięzłość):

 <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

Mógłbyś: usunąć cały kod, który nie jest istotny (Devise, attr_accessible, Carrierwave, inne powiązania, itp.); wyjaśnić, w jaki sposób tworzone są nowe relacje rodzinne (jaka jest rola tokena zaproszenia?). – tompave

+0

Również, jeśli to możliwe i stosowne, abstrakcja z dala od szczegółów niskiego poziomu jako tokenów zaproszeń. Zadaj pytanie tylko o skojarzeniach. – tompave

+0

Ostatnia rzecz: wspomniałeś _tłumaczenia_. Co masz na myśli? Zdolność Railsów do odmiany nazw skojarzeń? Czy chcesz wiedzieć o tym, aby zautomatyzować generowanie ciągów w widoku? – tompave

Odpowiedz

2

użyłbym tych samych stosunków zdefiniowano w pytaniu, z wyjątkiem tej części:

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) 

Z zwrotnego after_create do odwróć utworzone członkostwo:

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 

En glish nie jest moim ojczystym językiem, kod ten prawdopodobnie nie ma spójności (koherencji, logiki).

Mam nadzieję, że to pomoże!

+0

Skąd pochodzi 'internal_reference'? Czy to jest metoda Rails? Jeśli tak, czy masz link do niego? – marcamillion

+0

To nie jest metoda Rails, to wartość przechowywana w DB, kontroler przez ciebie (Admin App). Możesz więc użyć tej samej relacji, używając wewnętrznego odnośnika i w razie potrzeby przetłumaczyć ją na kilka języków. Poza tym nie używa słowa dokładnie "zamiast" dad = Relation.where (imię: "Tata"). "Po pierwsze" używasz inner_reference, która zawsze będzie taka sama, nawet dla "Dad", "Father", "Papa" (francuski), itp. – MrYoshiji

+0

co z nazwą "relacji", skąd się wzięło? A może chodziło Ci o 'relation.name'? tj. 'self.relation.name' gdzie' self' jest instancją klasy 'Membership'? Czy w ten sposób, gdy utworzę model 'Relation', muszę go wstępnie wypełnić paczką rekordów dla każdego typu relacji? tj. "syn, córka, ojciec, matka, dziadek itd."? – marcamillion

Powiązane problemy