I'm using hstore
on one of my models to store a hash with float values. I need to periodically access and perform calculations the values in the store.
My current solution for working with these values is to convert them to float everywhere I access them, which is very un-DRY. Is there a way for me to modify the store_accessor method to automatically covert any values that I read from the store to floats?
I know I can do this to specific keys by writing a function for them as described in the docs but I have a very long list of possible keys, so this way is also not very DRY.
I havent used hstore
before, but studied the documentation you provided in the question. Well, hstore
looks really useful (too bad it is available only in postgreSQL DB, but definitely learned something new).
From reading the documentation,
NOTE - If you are using PostgreSQL specific columns like hstore or json there is no need for the serialization provided by store. 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.
Also:
The stored attribute names can be retrieved using stored_attributes.
User.stored_attributes[:settings] # [:color, :homepage]
So, we will be getting the seperate fields in a stored_attribute
using stored_attributes
hash and will be getting the fields we declared on the stored_attribute
as an array. Now, we need to override the accessors for all the elements in the array. We can use define_method to dynamically override the accessors. This is what I came up with.
class WorkingBill < ActiveRecord::Base
store_accessor :prices, :cost_price, :selling_price
stored_attributes[:prices].each do |price_column_name|
define_method("#{key}=") do |value|
super(value.to_f)
end
define_method(key) do
super.to_f
end
end
end
I havent tested this code as I dont have a development environment right now. Also, I have a doubt whether super
call will work inside define_method
. So, just try it out. I will also test it once I get a development environment.
Also, as @Vakily commented, the gem https://github.com/jalkoby/active_store_accessor seems to do this better and also handles boolean, integer fields also.