为 rails 中的 JSON 列中的键在模型上定义虚拟属性的正确方法
Correct way to define virtual attributes on a Model for the keys in a JSON column in rails
在我的 rails 模型中,我有一个 JSON 列来存储一些元信息。
这是用户从表单输入的。
由于 JSON 列的键不是模型的属性,所以我不能在 form_for
中直接使用它们,而是需要定义一个虚拟属性。
由于虚拟属性的数量可能增长到任意长度,我想使用元编程来定义属性。
我确实尝试了 this question 中的答案,但是当我在我的模型中使用常量时,我收到一条错误消息,指出该常量未定义。所以我直接在数组中添加了键的符号,并在模块中迭代它们。当我这样做时,我收到一条错误消息,提示堆栈级别太深。
有人可以帮我吗?
我明白了。我 return 属性作为 JSON 列的键,现在它工作正常。
# lib/virtuals.rb
module Virtuals
%W(key_1 key_2 key_3).each do |attr|
define_method(attr) do
self.my_json_column[attr]
end
define_method("#{attr}=") do |val|
self.my_json_column[attr] = val
end
end
end
在我的模型中,我只需要包含上面的模块,它在 form_for
中工作正常并且也可以正确更新。
如果您正在使用 PostgreSQL
特定列,例如 hstore
或 json
,只需使用 store_accessor
来生成访问器方法。 请注意,这些列使用字符串键控哈希并且不允许使用符号进行访问。
class Model < ActiveRecord::Base
store_accessor :my_json_column, [ :key_1, :key_2, key_3 ]
end
它在做什么?它定义了 write\read 辅助方法:
def store_accessor(store_attribute, *keys)
keys = keys.flatten
_store_accessors_module.module_eval do
keys.each do |key|
define_method("#{key}=") do |value|
write_store_attribute(store_attribute, key, value)
end
define_method(key) do
read_store_attribute(store_attribute, key)
end
end
end
# .....
在我的 rails 模型中,我有一个 JSON 列来存储一些元信息。 这是用户从表单输入的。
由于 JSON 列的键不是模型的属性,所以我不能在 form_for
中直接使用它们,而是需要定义一个虚拟属性。
由于虚拟属性的数量可能增长到任意长度,我想使用元编程来定义属性。
我确实尝试了 this question 中的答案,但是当我在我的模型中使用常量时,我收到一条错误消息,指出该常量未定义。所以我直接在数组中添加了键的符号,并在模块中迭代它们。当我这样做时,我收到一条错误消息,提示堆栈级别太深。
有人可以帮我吗?
我明白了。我 return 属性作为 JSON 列的键,现在它工作正常。
# lib/virtuals.rb
module Virtuals
%W(key_1 key_2 key_3).each do |attr|
define_method(attr) do
self.my_json_column[attr]
end
define_method("#{attr}=") do |val|
self.my_json_column[attr] = val
end
end
end
在我的模型中,我只需要包含上面的模块,它在 form_for
中工作正常并且也可以正确更新。
如果您正在使用 PostgreSQL
特定列,例如 hstore
或 json
,只需使用 store_accessor
来生成访问器方法。 请注意,这些列使用字符串键控哈希并且不允许使用符号进行访问。
class Model < ActiveRecord::Base
store_accessor :my_json_column, [ :key_1, :key_2, key_3 ]
end
它在做什么?它定义了 write\read 辅助方法:
def store_accessor(store_attribute, *keys)
keys = keys.flatten
_store_accessors_module.module_eval do
keys.each do |key|
define_method("#{key}=") do |value|
write_store_attribute(store_attribute, key, value)
end
define_method(key) do
read_store_attribute(store_attribute, key)
end
end
end
# .....