Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field of Type Hash #231

Open
SimBed opened this issue Oct 17, 2022 · 0 comments
Open

Field of Type Hash #231

SimBed opened this issue Oct 17, 2022 · 0 comments

Comments

@SimBed
Copy link

SimBed commented Oct 17, 2022

Thanks for this gem. I’ve found it very helpful.

I run into a problem with it though when working with a field of type hash.

With the example given in the installation readme, when I first view the settings page in the browser, the default hash displays ok in the form. After form submission, the hash doesn’t get saved to the database and on page re-render the form displays
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess {}

The problem is in base.rb#L159 in the _convert_string_to_typeof_value method.
YAML.safe_load(value).to_h fails with error:
Tried to load unspecified class: Symbol (Psych::DisallowedClass).
This is because value has class HashWithIndifferentAccess, which safe_load doesn’t like.

I first thought this was a bug which could be resolved by either:
editing to YAML.safe_load(value, permitted_classes: [Symbol, ActiveSupport::HashWithIndifferentAccess]).to_h
(which is fine for my use case, but this presumably overrides the intended security feature of safe_load)

Or

Removing the line ActiveSupport::HashWithIndifferentAccess.new(value) and sticking with a hash.
(ok for my use case, but means referencing the hash only with string syntax, but eliminates the usefulness of HashWithIndifferentAccess and presumably breaks a load of apps that are using the gem).

I think though, the issue can be most effectively resolved without changing the gem, but by changing the value of the text_area form helper (in the view for the settings form) from:
YAML.dump(Setting.notification_options) to
YAML.dump(Setting.notification_options).gsub('!ruby/hash:ActiveSupport::HashWithIndifferentAccess','')

So set:
@notification_options =YAML.dump(Setting.notification_options).gsub('!ruby/hash:ActiveSupport::HashWithIndifferentAccess','')
in the the show method of the Settings Controller
and amend the example in app/views/admin/settings/show.html.erb to

  <div class="form-group">
    <label class="control-label">Notification options</label>
    <%= f.text_area :notification_options, value: @notification_options , class: "form-control", style: "height: 180px;"  %>
    <div class="form-text">
    </div>
  </div>

Also the default hash must have its keys in string (not symbol) format so amend the line in Setting.rb to:

field :notification_options, type: :hash, default: {
    "send_all"=> true,
    "logging"=> true,
    "sender_email"=> "[email protected]"
  }

I can see there is extensive test coverage, but was struggling to get my head round some of the meta-programming to see why this issue wasn’t being caught by the tests. I’m on Rails 6.1.6 and Ruby 3.0.1.

I hope this is helpful and would be interested to hear your thoughts.
Thank you
Daniel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant