Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to edit Rails serialized hashes in a form?

I have a model in my Rails app for a Bulletin, and when it is created, a lot of the values are stored in the database as serialized hashes or arrays, to be accessed later. I'm trying to create an edit view for just one of those hashes, but I can't figure out how to access it in my form.

The hash looks like this when stored:

top_offices = { first_office: "Office Name", first_office_amount: 1234.50, 
second_office: "Office Name", second_office_amount: 1234.50 }

And so on... there are five offices.

So in the console I can edit the values by doing:

bulletin = Bulletin.last
bulletin.top_offices[:first_office] = "New Office"
bulletin.top_offices[:first_office_amount] = 1234.00
bulletin.save

I can't figure out how to make a form that allows me to assign those values properly. I don't even actually need the form to populate with the previously stored values because I'm changing them completely any time I use the form.

like image 709
Glynne McReynolds Avatar asked May 22 '13 11:05

Glynne McReynolds


1 Answers

Option 1: Single instance method to update serialized attribute

As far as I know it's not possible to edit directly from a form a serialized attribute.

When I have this kind of things I'm always creating an instance method in the model that receive params and do the update (Could also do the save if I end the method name with a bang (!)).

In your case I would do the following:

class Bulletin

  ...

  def update_top_offices!(params)
    params.each do |key, value|
      self.top_offices[key] = value
    end

    self.save
  end

  ...
end

Option 2: A getter/setter per serialized attribute keys

Also another possibility if you really want to use a form to update the serialized attribute is to create a getter/setter as following:

class Bulletin

  ...

  def first_office
    self.top_offices[:first_office]
  end

  def first_office=(value)
    self.top_offices[:first_office] = value
  end

  ...
end

But then don't forget to save updated values.

Options 3: Overriding method_missing

A last possibility is to override method_missing but it's a bit more complex.

like image 187
ZedTuX Avatar answered Sep 20 '22 05:09

ZedTuX