未验证 提交 ff6d4987 编写于 作者: A Andrew White 提交者: GitHub

Merge pull request #32306 from danhuynhdev/feature/store-accessor-prefix

Add custom prefix to ActiveRecord::Store accessors
* Add custom prefix option to ActiveRecord::Store.store_accessor.
*Tan Huynh*
* Rails 6 requires Ruby 2.4.1 or newer.
*Jeremy Daer*
......
......@@ -31,10 +31,14 @@ 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
# 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.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
#
# # There is no difference between strings and symbols for accessing custom attributes
......@@ -44,6 +48,7 @@ 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
# end
#
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
......@@ -81,19 +86,29 @@ class << self
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], prefix: options[:prefix]) if options.has_key? :accessors
end
def store_accessor(store_attribute, *keys)
def store_accessor(store_attribute, *keys, prefix: nil)
keys = keys.flatten
accessor_prefix =
case prefix
when String, Symbol
"#{prefix}_"
when TrueClass
"#{store_attribute}_"
else
""
end
_store_accessors_module.module_eval do
keys.each do |key|
define_method("#{key}=") do |value|
define_method("#{accessor_prefix}#{key}=") do |value|
write_store_attribute(store_attribute, key, value)
end
define_method(key) do
define_method("#{accessor_prefix}#{key}") do
read_store_attribute(store_attribute, key)
end
end
......
......@@ -8,7 +8,12 @@ class StoreTest < ActiveRecord::TestCase
fixtures :'admin/users'
setup do
@john = Admin::User.create!(name: "John Doe", color: "black", remember_login: true, height: "tall", is_a_good_guy: true)
@john = Admin::User.create!(
name: "John Doe", color: "black", remember_login: true,
height: "tall", is_a_good_guy: true,
parent_name: "Quinn", partner_name: "Dallas",
partner_birthday: "1997-11-1"
)
end
test "reading store attributes through accessors" do
......@@ -24,6 +29,21 @@ class StoreTest < ActiveRecord::TestCase
assert_equal "37signals.com", @john.homepage
end
test "reading store attributes through accessors with prefix" do
assert_equal "Quinn", @john.parent_name
assert_nil @john.parent_birthday
assert_equal "Dallas", @john.partner_name
assert_equal "1997-11-1", @john.partner_birthday
end
test "writing store attributes through accessors with prefix" do
@john.partner_name = "River"
@john.partner_birthday = "1999-2-11"
assert_equal "River", @john.partner_name
assert_equal "1999-2-11", @john.partner_birthday
end
test "accessing attributes not exposed by accessors" do
@john.settings[:icecream] = "graeters"
@john.save
......
......@@ -19,6 +19,9 @@ def load(s)
store :params, accessors: [ :token ], coder: YAML
store :settings, accessors: [ :color, :homepage ]
store_accessor :settings, :favorite_food
store :parent, accessors: [:birthday, :name], prefix: true
store :spouse, accessors: [:birthday], prefix: :partner
store_accessor :spouse, :name, prefix: :partner
store :preferences, accessors: [ :remember_login ]
store :json_data, accessors: [ :height, :weight ], coder: Coder.new
store :json_data_empty, accessors: [ :is_a_good_guy ], coder: Coder.new
......
......@@ -21,6 +21,8 @@
create_table :admin_users, force: true do |t|
t.string :name
t.string :settings, null: true, limit: 1024
t.string :parent, null: true, limit: 1024
t.string :spouse, null: true, limit: 1024
# MySQL does not allow default values for blobs. Fake it out with a
# big varchar below.
t.string :preferences, null: true, default: "", limit: 1024
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册