Skip to content

Instantly share code, notes, and snippets.

@ngelx
Last active June 21, 2023 06:09
Show Gist options
  • Save ngelx/9cd2f8989f2ffb2975cffbe937ba05e9 to your computer and use it in GitHub Desktop.
Save ngelx/9cd2f8989f2ffb2975cffbe937ba05e9 to your computer and use it in GitHub Desktop.
ActiveAdmin extension to add interface to rails-setting-cached > version 2.

ActiveAdmin extension for rails-setting-cached > v2

This is an ActiveAdmin extension to add the interface to handle rails-setting-cached v2. For prior version I was using activeadmin_setting_cached but seems to be dead and does not support version > 2.

The initial idea was to extend that gem and do a PR, but the code is quite old and probably overcomplex. I may move this to a simple gem if there is any intereset on it.

How to use it

Just place the files in the proper places and should be ready to go.

<!-- app/views/admin/settings/_index.html.erb -->
<div>
<%= semantic_form_for :settings, method: :post, url: { action: :update } do |f| %>
<table id="setting_table" class="index_table index">
<% all_settings_by_scope.each_pair do |scope, settings| %>
<thead>
<tr>
<th colspan='2'><h3><%= scope.capitalize %></h3></th>
</tr>
</thead>
<tbody>
<% settings.each do |setting| %>
<tr class="odd">
<td><strong><%= f.label setting.key %></strong></td>
<td>
<div class='form'>
<ol><%= field_for_setting(f, setting) %></ol>
</div>
</td>
</tr>
<% end %>
</tbody>
<% end %>
</table>
<%= f.submit %>
<% end %>
</div>
# frozen_string_literal: true
# app/admin/setting.rb
ActiveAdmin.register_page 'Setting' do
menu label: proc { I18n.t('activeadmin.rails_setting_cache.menu.label') }
controller { helper SettingsHelper }
content title: 'Settings' do
all_settings_by_scope = Setting.defined_fields.reject { |field| field[:readonly] }.group_by { |field| field[:scope] }
render partial: 'admin/settings/index', locals: { all_settings_by_scope: all_settings_by_scope }
end
page_action :update, method: :post do
@errors = ActiveModel::Errors.new(Setting.new)
setting_params = params.require(:settings).permit!
update_something = false
setting_params.each_key do |key|
setting = Setting.find_or_initialize_by(var: key)
# NOTE: It would be amazing if from the setting we can get the field
field = Setting.get_field(key)
value = setting_params[key].presence
setting.value = if field[:type] == :hash
value.present? ? YAML.safe_load(value) : nil
else
value&.strip
end
update_something = true if setting.changed?
setting.save
@errors.merge!(setting.errors) unless setting.valid?
end
if @errors.any?
flash[:error] = t('activeadmin.rails_setting_cache.update.error', details: @errors.full_messages.join(', '))
else
message = update_something ? 'success' : 'nothing_updated'
flash[:success] = t("activeadmin.rails_setting_cache.update.#{message}")
end
Rails.version.to_i >= 5 ? redirect_back(fallback_location: admin_root_path) : redirect_to(:back)
end
end
# app/models/setting.rb
# NOTE: Setting model example.
class Setting < RailsSettings::Base
scope :testing do
field :welcome_message, type: :string, default: -> { "welcome to TEST" }, validates: { length: { maximum: 10 } }
field :default_locale, default: "zh-CN", validates: { presence: true, inclusion: { in: %w[zh-CN en jp] } }, option_values: %w[en zh-CN jp], help_text: "Bla bla ..."
field :admin_emails, type: :array, default: %w[admin@rubyonrails.org other@vla.com]
field :user_limits, type: :integer, default: 20
field :captcha_enable, type: :boolean, default: true
field :notification_options, type: :hash, default: {
send_all: true,
logging: true,
sender_email: "foo@bar.com"
}
field :readonly_item, type: :integer, default: 100, readonly: true
end
end
# config/locales/rails_setting_cached.en.yml
en:
activeadmin:
rails_setting_cache:
menu:
label: 'Settings'
update:
success: 'Setting updated'
error: 'Error updating setting. %{details}'
nothing_updated: 'Nothing was updated'
# app/helpers/settings_helpers.rb
module SettingsHelper
def field_for_setting(form, setting)
case setting.type
when :boolean
value = Setting.send("#{setting.key}?")
form.check_box setting.key, checked: value, label: false
when :array
value = Setting.send(setting.key.to_s).join("\n")
form.text_area setting.key, value: value, label: false, placeholder: setting.default.join("\n")
when :integer
form.number_field setting.key, label: false, value: Setting.send(setting.key.to_s), placeholder: setting.default
when :hash
value = YAML.dump(Setting.send(setting.key.to_s)).gsub(/^---.*\n*/,'')
form.text_area setting.key, value: value, label: false, placeholder: YAML.dump(setting.default).gsub(/^---.*\n*/,'')
else
if setting[:options].key?(:option_values)
form.select setting.key, setting[:options][:option_values], label: false, selected: Setting.send(setting.key.to_s)
else
value = Setting.send(setting.key.to_s)
form.text_field setting.key, label: false, value: value, placeholder: setting.default
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment