O que este código permite que você faça é criar um relacionamento pertence a / tem muitos para algo , mantendo apenas um de cada tipo por perfil de usuário.
Se algo vai, ou pode ter mais de um relacionamento belongs_to, então você deve usar relacionamentos polimórficos. A documentação online disponível sobre isso cobre basicamente o básico. Portanto, espero que este esboço de código lhe dê um entendimento mais profundo e encontre sucesso com relacionamentos polimórficos com Rails daqui em diante!
models / profile.rb
class Profile < ActiveRecord::Base
has_many :socials, as: :sociable, dependent: :destroy
accepts_nested_attributes_for :socials, allow_destroy: true
end
models / social.rb
class Social < ActiveRecord::Base
enum kind: [:twitter, :google_plus, :instagram, :facebook]
belongs_to :sociable, polymorphic: true
validates_presence_of :kind
validates_presence_of :username
end
controladores / profiles_controller.rb
class ProfilesController < ApplicationController
before_action :set_profile, only: [:show, :edit, :update, :destroy]
before_action :set_social_list, only: [:new, :edit]
def new
@profile=Profile.new
end
def edit
end
private
def set_profile
@profile = Profile.find( params[:id] )
end
def set_social_list
@social_list = [
[ "Twitter ID", :twitter ],
[ "Google Plus ID", :google_plus ],
[ "Instagram ID", :linked_in ],
[ "Facebook ID", :facebook ]
]
end
def profile_params
params.require(:profile).permit(
socials_attributes: [:id, :kind, :username, :_destroy]
)
end
end
Reduzi o arquivo real apenas para o que é relevante aqui. Você precisará de quaisquer outros parâmetros permitidos para seu caso de uso. O resto pode permanecer intocado.
controladores / application_controller.rb
class ApplicationController < ActionController::Base
def one_by_kind(obj, kind)
obj.where(:kind => kind).first || obj.where(:kind => kind).build
end
helper_method :one_by_kind
end
É aqui que a mágica acontecerá. Ele é projetado depois de .where (…) .first ou create, mas usa build em vez disso, então não temos que declarar build para o objeto social no profile_controller.
E, por último, a visão muito importante:
(polimórfico aspecto mais indocumentado).
views / profiles / _form.html
<% @social_list.each do |label, entry| %>
<%= f.fields_for :socials, one_by_kind(@profile.socials,
@profile.socials.kinds[entry]) do |a| %>
<%= a.hidden_field :kind, {value: entry} %><%= label %>:
<%= a.text_field :username %>
<% end %>
<% end %>
O @social_list é definido no profile_controller e é uma matriz de pares de rótulo e tipo. Assim, conforme cada um é passado, o método um por tipo que definimos no application_controller procura o primeiro filho polimórfico que tem o tipo certo que chamamos de entrada . Se o registro do banco de dados não for encontrado, ele será criado. um por tipo, então devolve o objeto para escrevermos / atualizarmos.
Isso mantém uma visão para criar e atualizar filhos polimórficos. Portanto, permite um de cada tipo dentro do seu perfil e relação social.
Sinta-se à vontade para deixar seus pensamentos, ideias e contribuições abaixo nos comentários. Compartilhar! Deus abençoe!