Reputation: 397
I have a model which has one actual column in the database. This column is stored as a JSON string of configuration. I use a bunch of virtual attributes which I want to map inside of this configuration JSON attribute. I basically dont want to create a bunch columns in the db, but rather use this one JSON attribute to contain everything. Is there a cleaner way than the below def
s of achieving this?
class Device < ActiveRecord::Base
attr_accessible :configuration
serialize :configuration, JSON
attr_accessor :background_color, :title
# below is ew
def background_color; self.configuration["background_color"]; end
def background_color=(value); self.configuration["background_color"] = value; end
def title; self.configuration["title"]; end
def title=(value); self.configuration["title"] = value; end
end
Ideally i'd be looking for something like attr_maps_to_hash :configuration, [:background_color, :title]
. Does something like this exist?
Upvotes: 0
Views: 653
Reputation: 11
Rails as of 3.2 has key-value stores built into ActiveRecord-see here:
Where can i read more about Rails 3.2's Data Store with key-value in textfield?
in your case you can have a text field named configuration and then do this:
class Device < AR::Base store :configuration, accessors: [:title, :background_color, ...] ...
This should work fine with forms, etc..
Upvotes: 1
Reputation: 1
Two methods come to mind.
First, you could have an array of your attributes [:background_color, :title] and then iterate over them while calling define_method. You would defined two methods, define(method_name) and define("#{method_name}=").
Second, a similar idea but using method missing.
def method_missing(method_name, *args, &block)
...see if it's a get or set...
...do your stuff...
...rain dance...
...yay...
end
Upvotes: 0
Reputation: 1053
You can use ActiveRecord::Store for this.
class User < ActiveRecord::Base
store :settings, accessors: [ :color, :homepage ]
end
u = User.new(color: 'black', homepage: '37signals.com')
u.color # Accessor stored attribute
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
# Add additional accessors to an existing store through store_accessor
class SuperUser < User
store_accessor :settings, :privileges, :servants
end
If you are using PostgreSQL, check out HStore.
Upvotes: 1