Mat*_*man 8 activerecord ruby-on-rails entity-attribute-value
在rails上使用ruby,我有一个Customer表,我希望能够添加无限属性(键值对).我不确定键/值对将是什么,所以我不知道如何做到这一点.例如,一个客户可能是:
基本上,客户可以在键/值对中拥有任意数量的属性.
我怎样才能做到这一点?
Jor*_*ing 11
执行此操作的"传统"方法是使用实体 - 属性 - 值或EAV模式.顾名思义,您将创建一个包含三列的新表:一个用于"实体",在本例中为Customer,一个用于"属性"名称或键,另一个用于值.所以你有一个像这样的表:
customer_properties
+----+-------------+--------------+------------+
| id | customer_id | key | value |
+----+-------------+--------------+------------+
| 1 | 1 | color | yellow |
| 2 | 1 | brand | nike |
| 3 | 1 | sales | 33 |
| 4 | 2 | color | red |
| 5 | 2 | phone_number | 1111111111 |
| 6 | 2 | purchases | 2 |
+----+-------------+--------------+------------+
Run Code Online (Sandbox Code Playgroud)
你肯定想要一个INDEX key,也许就是value(customer_id当然,但Rails会在你使用relation或belongs_to迁移时为你做到这一点).
然后在你的模型中:
# customer.rb
class Customer < ActiveRecord::Base
has_many :customer_properties
end
# customer_property.rb
class CustomerProperty < ActiveRecord::Base
belongs_to :customer
end
Run Code Online (Sandbox Code Playgroud)
这样可以使用如下:
customer = Customer.joins(:customer_properties)
.includes(:customer_properties)
.where(customer_properties: { key: "brand", value: "nike" })
.first
customer.customer_properties.each_with_object({}) do |prop, hsh|
hsh[prop.key] = prop.val
end
# => { "color" => "yellow",
# "brand" => "nike",
# "sales" => "33" }
customer.customer_properties.create(key: "email", value: "foo@bar.com")
# => #<CustomerProperty id: 7, customer_id: 1, key: "email", ...>
Run Code Online (Sandbox Code Playgroud)
随着数据库设计的进展,这是非常可靠的,但正如你所看到它有一些局限性:特别是,它很麻烦.此外,您只能使用单一值类型(:string/ VARCHAR是常见的).如果你走这条路线,你可能想要在Customer上定义一些便利方法,使访问和更新属性变得不那么麻烦.我猜可能有一些专门用于使EAV模式与ActiveRecord很好地配合使用的宝石,但我不知道它们在我的头脑中,我希望你能原谅我没有谷歌搜索,因为我是移动的.
正如Brad Werth指出的那样,如果你只需要存储任意属性而不是通过它们进行查询,那么它serialize是一个很好的选择,如果你使用PostgreSQL,即使查询问题也可以克服,因为它有很棒的hstore功能.
祝好运!
| 归档时间: |
|
| 查看次数: |
1860 次 |
| 最近记录: |