I have some global settings I want to be able to change through the user interface. The gem ‘rails-settings-cached’ seems to be the tool of choice for this.
I run into a problem with it though when working with a field of type hash.
With the example given in the installation readme (relevant code below for reference), when I first view the settings page in the browser, the default hash displays ok in the form (in YAML format). After form submission, the hash doesn’t get saved to the database and on page re-render the form displays --- !ruby/hash:ActiveSupport::HashWithIndifferentAccess {}.
On investigation, I found the offending line in the source code YAML.safe_load(value).to_h which fails with error ‘
Tried to load unspecified class: Symbol (Psych::DisallowedClass)
’ If I change this line to:
YAML.safe_load(value, permitted_classes: [Symbol, ActiveSupport::HashWithIndifferentAccess]).to_h
It works as expected. I’m on Rails 6.1.6 and Ruby 3.0.1 My questions:
- Am I missing something?
- How do I apply this workaround in production? One option I think would be to install the gem directly into my project file rather than adding to the gemfile (bundle install --path vendor/bundle) and make the edit directly from there (and then push to production).
- How do I give feedback to the gem author?
Thanks Daniel
app/models/setting.rb
class Setting < RailsSettings::Base
field :hash_test, type: :hash, default: {
logging: true,
email: "foo@bar.com"
}
end
config/routes.rb
resource :settings
settings_controller.rb
class SettingsController < ApplicationController
def create
setting_params.keys.each do |key|
Setting.send("#{key}=", setting_params[key].strip)
end
redirect_to admin_settings_path, notice: "Setting was successfully updated."
end
private
def setting_params
params.require(:setting).permit :notification_options)
end
end
app/views/settings/show.html.erb
<%= form_for(Setting.new, url: admin_settings_path) do |f| %>
<div class="form-group">
<label class="control-label">Notification options</label>
<%= f.text_area :notification_options, value: YAML.dump(Setting.notification_options), class: "form-control"%>
</div>
<div>
<%= f.submit 'Update Settings' %>
</div>
<% end %>