Store accessor for nested JSON
You can do this using the Attribute API
store_accessor :integrations, :mailchimp
store_accessor :mailchimp, :api_key, :list_id
attribute :mailchimp, :json # :jsonb also works if you're using a PG column of that type for `integrations`
You're right, unfortunately store_accessor
does not allow you to access nested keys. The reason is that store_accessor
is basically just a shortcut which defines getter and setter methods:
# here is a part of store_accessor method code, you can take a look at
# full implementation at
# http://apidock.com/rails/ActiveRecord/Store/ClassMethods/store_accessor
_store_accessors_module.module_eval do
keys.each do |key|
# here we define a setter for each passed key
define_method("#{key}=") do |value|
write_store_attribute(store_attribute, key, value)
end
# and here goes the getter
define_method(key) do
read_store_attribute(store_attribute, key)
end
end
end
So, your options here are:
To implement your own set of getter and setter methods manually:
# somewhere in your model def mailchimp_api_key self.mailchimp["api_key"] end def mailchimp_api_key= value self.mailchimp["api_key"] = value end
This solves a problem, but you'd have to write lots of this repeatedly for each of nested attributes.
To write your own helper method inside of
ActiveRecord::Store::ClassMethods
module which would define the same setter and getter methods dynamically for the set of attributes you pass in. You'd have to take the basic implementation of Railsstore_accessor
and add an additional hash keys iteration to it. Not sure if this is going to be an easy one, but would definitely be interesting to see shared as a gem.Leave Rails itself and use the power of postgres
json
type support with some pureSQL
code. For example, you can accessapi_key
attribute with something like that:SELECT integrations->'mailchimp'->>'api_key' as mailchimp_api_key FROM your_table_name;
More on postgres json queries can be found here.