rails-settings-cached – bug with hash field?

Viewed 65

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:

  1. Am I missing something?
  2. 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).
  3. 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 %>
0 Answers
Related