Configure the label of Active Admin has_many
-
25-10-2019 - |
سؤال
Well I have a two models related with a on-to-many assoc.
#models/outline.rb
class Outline < ActiveRecord::Base
has_many :documents
end
#models/document.rb
class Document < ActiveRecord::Base
belongs_to :outline
end
#admin/outlines.rb
ActiveAdmin.register Outline do
form do |f|
f.inputs "Details" do
f.input :name, :required => true
f.input :pages, :required => true
...
f.buttons
end
f.inputs "Document Versions" do
f.has_many :documents, :name => "Document Versions" do |d|
d.input :file, :as => :file
d.buttons do
d.commit_button :title => "Add new Document Version"
end
end
end
end
end
Well as you can see in the admin/outlines.rb I already tried setting up the :name, in the has_many :documents, and the :title in the commit_button, but neither of that options work, I also tried with :legend, :title, and :label, instead of :name in the .has_many. Not working.
This is the result of that code: Screenshot
What I want to display is "Document Versions" instead of "Documents", and "Add new Document Version" instead of "Add new Document"
If someone can have a solution it would be great
المحلول
To set has_many
header you can use
f.has_many :images, heading: 'My images' do |i|
i.input :src, label: false
end
See here
نصائح أخرى
Looking at ActiveAdmin tests("should translate the association name in header"), there may be another way of doing this. Use your translation file.
If you look at ActiveAdmin has_many method (yuck!!! 46 lines of sequential code), it uses ActiveModel's human method.
Try adding this to your translation file
en:
activerecord:
models:
document:
one: Document Version
other: Document Versions
One quick hack is that you can hide the h3 tag through its style.
assets/stylesheets/active_admin.css.scss
.has_many {
h3 {
display: none;
}}
This will hide any h3 tag under a has_many class.
Sjors answer is actually a perfect start to solving the question. I monkeypatched Active Admin in config/initializers/active_admin.rb with the following:
module ActiveAdmin
class FormBuilder < ::Formtastic::FormBuilder
def titled_has_many(association, options = {}, &block)
options = { :for => association }.merge(options)
options[:class] ||= ""
options[:class] << "inputs has_many_fields"
# Set the Header
header = options[:header] || association.to_s
# Add Delete Links
form_block = proc do |has_many_form|
block.call(has_many_form) + if has_many_form.object.new_record?
template.content_tag :li do
template.link_to I18n.t('active_admin.has_many_delete'), "#", :onclick => "$(this).closest('.has_many_fields').remove(); return false;", :class => "button"
end
else
end
end
content = with_new_form_buffer do
template.content_tag :div, :class => "has_many #{association}" do
form_buffers.last << template.content_tag(:h3, header.titlecase) #using header
inputs options, &form_block
# Capture the ADD JS
js = with_new_form_buffer do
inputs_for_nested_attributes :for => [association, object.class.reflect_on_association(association).klass.new],
:class => "inputs has_many_fields",
:for_options => {
:child_index => "NEW_RECORD"
}, &form_block
end
js = template.escape_javascript(js)
js = template.link_to I18n.t('active_admin.has_many_new', :model => association.to_s.singularize.titlecase), "#", :onclick => "$(this).before('#{js}'.replace(/NEW_RECORD/g, new Date().getTime())); return false;", :class => "button"
form_buffers.last << js.html_safe
end
end
form_buffers.last << content.html_safe
end
end
end
Now in my admin file I call titled_has_many just like has_many but I pass in :header to override the use of the Association as the h3 tag.
f.titled_has_many :association, header: "Display this as the H3" do |app_f|
#stuff here
end
You can customise the label of the "Add..." button by using the new_record
setting on has_many
. For the heading label you can use heading
:
f.has_many :documents,
heading: "Document Versions",
new_record: "Add new Document Version" do |d|
d.input :file, :as => :file
end
Does not deserve a prize but you could put this in config/initializers/active_admin.rb . It will allow you to tweak the headers you want using a config/locales/your_file.yml (you should create the custom_translations entry yourself). Dont forget to restart the server. And use the f.hacked_has_many in your form builder.
module ActiveAdmin
class FormBuilder < ::Formtastic::FormBuilder
def hacked_has_many(association, options = {}, &block)
options = { :for => association }.merge(options)
options[:class] ||= ""
options[:class] << "inputs has_many_fields"
# Add Delete Links
form_block = proc do |has_many_form|
block.call(has_many_form) + if has_many_form.object.new_record?
template.content_tag :li do
template.link_to I18n.t('active_admin.has_many_delete'), "#", :onclick => "$(this).closest('.has_many_fields').remove(); return false;", :class => "button"
end
else
end
end
content = with_new_form_buffer do
template.content_tag :div, :class => "has_many #{association}" do
# form_buffers.last << template.content_tag(:h3, association.to_s.titlecase)
# CHANGED INTO
form_buffers.last << template.content_tag(:h3, I18n.t('custom_translations.'+association.to_s))
inputs options, &form_block
# Capture the ADD JS
js = with_new_form_buffer do
inputs_for_nested_attributes :for => [association, object.class.reflect_on_association(association).klass.new],
:class => "inputs has_many_fields",
:for_options => {
:child_index => "NEW_RECORD"
}, &form_block
end
js = template.escape_javascript(js)
_model = 'activerecord.models.' + association.to_s.singularize
_translated_model = I18n.t(_model)
js = template.link_to I18n.t('active_admin.has_many_new', :model => _translated_model), "#", :onclick => "$(this).before('#{js}'.replace(/NEW_RECORD/g, new Date().getTime())); return false;", :class => "button"
form_buffers.last << js.html_safe
end
end
form_buffers.last << content.html_safe
end
end
end
If you have issues with locale files not being loaded good in staging/production mode, adding this to your application.rb might help (substitute :nl for the right locale)
config.before_configuration do
I18n.load_path += Dir[Rails.root.join('config','locales','*.{rb,yml}').to_s]
I18n.locale = :nl
I18n.default_locale = :nl
config.i18n.load_path += Dir[Rails.root.join('config','locales','*.{rb,yml}').to_s]
config.i18n.locale = :nl
config.i18n.default_locale = :nl
I18n.reload!
config.i18n.reload!
end
config.i18n.locale = :nl
config.i18n.default_locale = :nl