Então, vamos definir o cenário. Você está usando Atos como Relação porque permite que você defina herança dentro de seus modelos, no meu caso eu tinha uma Apresentação que estava estendendo um Recurso
# app/models/presentation.rb
class Presentation < ActiveRecord::Base
acts_as :resource
attr_accessible :markup
end
# app/models/resource.rb
class Resource < ActiveRecord::Base
acts_as_superclass
belongs_to :topic
belongs_to :level
attr_accessible :name, :topic, :level
end
Você também notará que um Recurso tem um Tópico e um Nível ao qual pertence.
# app/models/topic.rb
class Topic < ActiveRecord::Base
attr_accessible :name
has_many :resources
end
# app/models/level.rb
class Level < ActiveRecord::Base
attr_accessible :name
has_many :resources
end
Por fim, queremos que tudo isso funcione bem com a incrível gem ActiveAdmin , que cria uma interface de administração adorável para quaisquer modelos que você definir. Neste caso, eu queria ter uma seção ‘Apresentação’ onde pudesse criar uma Apresentação com um nome , definir seu nível e tópico a partir das listas suspensas dos registros disponíveis atualmente para esses dois tipos e, finalmente, escrever alguma marcação . Portanto, há coisas vindo de vários modelos diferentes, para a mesma tela, e no caso do ActiveAdmin , isso significa trabalhar com Formtastic . A primeira coisa que você precisa fazer é gerar seu modelo ActiveAdmin
rails generate active_admin:resource Presentation
Se você então pular para a sua área de administração, verá que ela criou uma seção de Apresentação , mas atualmente contém apenas o campo de marcação que vem diretamente do modelo de Apresentação . Adicionar o nome do modelo de recursos é bastante simples, você só precisa adicioná-lo, pois ele não foi selecionado pelo gerador ActiveAdmin .
# app/admin/presentations.rb
ActiveAdmin.register Presentation do
form do |f|
f.inputs do
f.input :name
f.input :markup
end
f.buttons
end
end
Portanto, agora queremos adicionar os seletores de nível e tópico , que devem incluir todas as entradas possíveis em seus respectivos modelos. Felizmente, o Formtastic tem uma maneira bastante boa de fazer isso em uma única linha para cada modelo
# app/admin/presentations.rb
...
f.input :name
f.input :level, :as => :select, :collection => Level.all, :include_blank => false, :selected => (presentation.level.id if !presentation.level.nil?)
f.input :topic, :as => :select, :collection => Topic.all, :include_blank => false, :selected => (presentation.topic.id if !presentation.topic.nil?)
f.input :markup
...
Se você tentar o formulário neste ponto, provavelmente descobrirá que obtém um erro ActiveRecord :: AssociationTypeMismatch , e isso se resume ao Formtastic usando a referência de nível e id de tópico no formulário. Para consertar isso, você precisa realmente ir para o controlador do ActiveAdmin e modificar seu método de criação , novamente, felizmente, bastante simples. Neste ponto, também adicionarei a função de índice do ActiveAdmin para que possamos ver os campos corretos no índice também:
ActiveAdmin.register Presentation do
form do |f|
f.inputs do
f.input :name
f.input :level, :as => :select, :collection => Level.all, :include_blank => false, :selected => (presentation.level.id if !presentation.level.nil?)
f.input :topic, :as => :select, :collection => Topic.all, :include_blank => false, :selected => (presentation.topic.id if !presentation.topic.nil?)
f.input :markup
end
f.buttons
end
index do
column :name
column :level
column :topic
column :markup
default_actions
end
controller do
def create
@level = Level.find(params[:presentation][:level])
@topic = Topic.find(params[:presentation][:topic])
params[:presentation][:level] = @level
params[:presentation][:topic] = @topic
@presentation = Presentation.new(params[:presentation])
super
end
end
end
E isso basta! Embora pareça bastante complicado, na verdade representa uma base bastante complexa e facilmente extensível para criar muitos modelos diferentes feitos dos mesmos bits.