Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Rails Form Helpers with Serialized Custom Classes

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.

like image 301
IH012345 Avatar asked Sep 21 '10 19:09

IH012345


1 Answers

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?)

like image 197
Dmitry Polushkin Avatar answered Oct 23 '22 09:10

Dmitry Polushkin