aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/store.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/store.rb')
-rw-r--r--activerecord/lib/active_record/store.rb51
1 files changed, 42 insertions, 9 deletions
diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb
index 006afe7495..3537e2d008 100644
--- a/activerecord/lib/active_record/store.rb
+++ b/activerecord/lib/active_record/store.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/indifferent_access"
module ActiveRecord
@@ -15,8 +17,8 @@ module ActiveRecord
# You can set custom coder to encode/decode your serialized attributes to/from different formats.
# JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
#
- # NOTE: If you are using PostgreSQL specific columns like +hstore+ or +json+ there is no need for
- # the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
+ # NOTE: If you are using structured database data types (eg. PostgreSQL +hstore+/+json+, or MySQL 5.7+
+ # +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
# Simply use {.store_accessor}[rdoc-ref:ClassMethods#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.
@@ -29,10 +31,18 @@ module ActiveRecord
#
# class User < ActiveRecord::Base
# store :settings, accessors: [ :color, :homepage ], coder: JSON
+ # store :parent, accessors: [ :name ], coder: JSON, prefix: true
+ # store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
+ # store :settings, accessors: [ :two_factor_auth ], suffix: true
+ # store :settings, accessors: [ :login_retry ], suffix: :config
# end
#
- # u = User.new(color: 'black', homepage: '37signals.com')
+ # u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
# u.color # Accessor stored attribute
+ # u.parent_name # Accessor stored attribute with prefix
+ # u.partner_name # Accessor stored attribute with custom prefix
+ # u.two_factor_auth_settings # Accessor stored attribute with suffix
+ # u.login_retry_config # Accessor stored attribute with custom suffix
# u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
#
# # There is no difference between strings and symbols for accessing custom attributes
@@ -42,11 +52,13 @@ module ActiveRecord
# # Add additional accessors to an existing store through store_accessor
# class SuperUser < User
# store_accessor :settings, :privileges, :servants
+ # store_accessor :parent, :birthday, prefix: true
+ # store_accessor :settings, :secret_question, suffix: :config
# end
#
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
#
- # User.stored_attributes[:settings] # [:color, :homepage]
+ # User.stored_attributes[:settings] # [:color, :homepage, :two_factor_auth, :login_retry]
#
# == Overwriting default accessors
#
@@ -79,19 +91,40 @@ module ActiveRecord
module ClassMethods
def store(store_attribute, options = {})
serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
- store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
+ store_accessor(store_attribute, options[:accessors], options.slice(:prefix, :suffix)) if options.has_key? :accessors
end
- def store_accessor(store_attribute, *keys)
+ def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
keys = keys.flatten
+ accessor_prefix =
+ case prefix
+ when String, Symbol
+ "#{prefix}_"
+ when TrueClass
+ "#{store_attribute}_"
+ else
+ ""
+ end
+ accessor_suffix =
+ case suffix
+ when String, Symbol
+ "_#{suffix}"
+ when TrueClass
+ "_#{store_attribute}"
+ else
+ ""
+ end
+
_store_accessors_module.module_eval do
keys.each do |key|
- define_method("#{key}=") do |value|
+ accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"
+
+ define_method("#{accessor_key}=") do |value|
write_store_attribute(store_attribute, key, value)
end
- define_method(key) do
+ define_method(accessor_key) do
read_store_attribute(store_attribute, key)
end
end
@@ -133,7 +166,7 @@ module ActiveRecord
end
def store_accessor_for(store_attribute)
- type_for_attribute(store_attribute.to_s).accessor
+ type_for_attribute(store_attribute).accessor
end
class HashAccessor # :nodoc: