Akshay Pardhanani Akshay Pardhanani - 10 months ago 55
Ruby Question

Correct way to define virtual attributes on a Model for the keys in a JSON column in rails

In my rails model I have a JSON column which stores some meta information.
This is to be entered bu the user from a form.

Since the keys of the JSON column are not attributes of the model I cannot use them directly in

instead I need to define a virtual attribute.

Since this number of virtual attributes could grow to be arbitrarily lengthy I would like to use meta programming to define the attributes.

I did try the answer in this question however when I use the constant in my model I get an error saying that the constant is undefined. So I added the symbols for the keys in an array directly and iterate over them in the module. When I do this I get an error that says stack level too deep.

Please can someone help me out here?


If you are using PostgreSQL specific columns like hstore or json simply use store_accessor instead to generate the accessor methods. Be aware that these columns use a string keyed hash and do not allow access using a symbol.

class Model < ActiveRecord::Base
  store_accessor :my_json_column, [ :key_1, :key_2, key_3 ]

What it doing under the hood? It has define write\read helper methods:

def store_accessor(store_attribute, *keys)
  keys = keys.flatten

  _store_accessors_module.module_eval do
    keys.each do |key|
      define_method("#{key}=") do |value|
        write_store_attribute(store_attribute, key, value)

      define_method(key) do
        read_store_attribute(store_attribute, key)

# .....