Criação Polimórfica Manual em Trilhos

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!