0

我有一个模型,它在数据库中有一个实际列。此列存储为 JSON 配置字符串。我使用了一堆我想在这个配置 JSON 属性中映射的虚拟属性。我基本上不想在数据库中创建一堆列,而是使用这个 JSON 属性来包含所有内容。有没有比以下更清洁def的方法来实现这一目标?

class Device < ActiveRecord::Base
  attr_accessible :configuration
  serialize :configuration, JSON

  attr_accessor :background_color, :title

  # below is ew
  def background_color; self.configuration["background_color"]; end
  def background_color=(value); self.configuration["background_color"] = value; end

  def title; self.configuration["title"]; end
  def title=(value); self.configuration["title"] = value; end
end

理想情况下,我会寻找类似的东西attr_maps_to_hash :configuration, [:background_color, :title]。这样的事情存在吗?

4

3 回答 3

1

您可以为此使用ActiveRecord::Store

class User < ActiveRecord::Base
  store :settings, accessors: [ :color, :homepage ]
end

u = User.new(color: 'black', homepage: '37signals.com')
u.color                          # Accessor stored attribute
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor

# Add additional accessors to an existing store through store_accessor
class SuperUser < User
  store_accessor :settings, :privileges, :servants
end

如果您使用的是 PostgreSQL,请查看HStore

于 2013-03-21T21:59:07.020 回答
1

Rails 自 3.2 起在 ActiveRecord 中内置了键值存储 - 请参见此处:

我在哪里可以阅读更多关于 Rails 3.2 的数据存储与文本字段中的键值的信息?

在您的情况下,您可以有一个名为 configuration 的文本字段,然后执行以下操作:

class Device < AR::Base store :configuration, accessors: [:title, :background_color, ...] ...

这应该适用于表单等。

于 2013-03-21T22:00:45.393 回答
0

想到了两种方法。

首先,您可以拥有一个属性数组 [:background_color, :title],然后在调用 define_method 时遍历它们。您将定义两个方法,define(method_name) 和 define("#{method_name}=")。

第二,类似的想法,但使用方法缺失。

def method_missing(method_name, *args, &block)
  ...see if it's a get or set...
  ...do your stuff...
  ...rain dance...
  ...yay...
end
于 2013-03-21T22:00:41.613 回答