I'm trying to save a hash of options in a single DB field. The form is able to save the data to the DB but not able to retrieve it again when I go to edit it (e.g. all the other fields are prepopulated except for the wp_options fields).
class Profile < ActiveRecord::Base
serialize :wp_options
end
This is my custom class:
class WP_Options
attr_accessor :wp_name, :wp_desc, :wp_limit
end
In my form:
<%= form_for(@profile, :remote => true) do |f| %>
...
<%= f.fields_for :wp_options do |wp_options| %>
<%= wp_options.text_field :wp_name %>
<% end %>
...
In my controller:
@profile = Profile.new(:wp_options => WP_Options.new)
In my DB column 'wp_options':
--- !map:ActiveSupport::HashWithIndifferentAccess
wp_name: Test
Any advice would be really appreciated.
Actually it's easy. You need to use class with reader
methods. You can create it with a different ways, but the easiest one is to use OpenStruct
class (notice, that it will be unable to see fields that are in the OpenStruct's instance methods... this class cannot redefine methods).
In your form you should add:
<%= f.fields_for :wp_options, @profile.wp_options do |wp_options| %>
Instead of @profile (if you have dynamic variable) you can use f.object.wp_options
.
And to the model Profile
you should add wp_options
method.
def wp_options
OpenStruct.new(self.attributes['wp_options'])
end
In that case it will only work if your serialized wp_options is a Hash class.
Hope that helps.
PS. I used same technique, but because I had type
hash keys, OpenStruct were unable to create it, so I used simple Struct class. I had data
column:
def data
keys = current_data.keys
data = attributes[:data]
Struct.new(*keys).new(*keys.map { |k| data[k] })
end
A little less trivial, but anyway the same approach (before that I've created special class, but now I know that Struct is the better way to creating of that kind stuff. More ideas you can find here: How do I use hash keys as methods on a class?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With