我希望能够将“元”信息添加到模型中,基本上是用户定义的字段。因此,举例来说,让我们想象一下用户模型:
我定义名字,姓氏,年龄,性别的字段。
我希望用户能够定义一些“元信息”,基本上可以进入他们的个人资料页面并分享其他信息。因此,一个用户可能想要添加“爱好”,“职业”和“家乡”,而另一个用户可能想要添加“爱好”和“教育”。
所以,我希望能够为这种东西提供标准视图,所以例如在视图中我可以做一些像(在HAML中)的东西:
- for item in @meta
%li
%strong= item.key + ":"
= item.value
通过这种方式,我可以确保始终如一地显示信息,而不仅仅是向用户提供可以以不同方式格式化的降价文本框。
我也希望能够点击meta并查看已经给出相同内容的其他用户,因此在上面的示例中,两个用户都定义了“爱好”,能够说我想要看到有共享兴趣爱好的用户 - 或者甚至更好,我希望看到其兴趣爱好 _ __ 的用户。
所以,既然我不知道用户想要提前定义哪些字段,那么提供这种功能有哪些选择呢?
是否有一个gem可以在这样的模型上处理自定义元信息,或者至少有类似的东西?有没有人遇到过这种问题?如果是这样,你是如何解决的?
谢谢!
答案 0 :(得分:7)
动态字段实现取决于以下因素:
通常,解决方案无法满足所有要求。迈克的解决方案优雅地解决了1和5问题。你应该使用他的解决方案1& 5对你很重要。
这是一个解决1,2,3,4和5
的长解决方案 更新users
表格
将名为text
的{{1}}字段添加到users表。
更新您的meta
型号
User
添加新的元字段
class User < ActiveRecord::Base
serialize :meta, Hash
def after_initialize
self.meta ||= {} if new_record?
end
end
访问元字段
u = User.first
u.meta[:hobbies] = "skiing"
u.save
迭代元字段
puts "hobbies=#{u.meta[:hobbies]}"
要满足第5项要求,您需要使用Solr Or Sphinx全文搜索引擎。它们比依赖数据库进行u.meta.each do |k, v|
puts "#{k}=#{v}"
end
查询更有效。
如果您通过Sunspot gem使用Solr,这是一种方法。
LIKE
查找类似用户
class User
searchable do
integer(:user_id, :using => :id)
meta.each do |key, value|
t = solr_type(value)
send(t, key.to_sym) {value} if t
end
end
def solr_type(value)
return nil if value.nil?
return :integer if value.is_a?(Fixnum)
return :float if value.is_a?(Float)
return :string if value.is_a?(String)
return :date if value.is_a?(Date)
return :time if value.is_a?(Time)
end
def similar_users(*args)
keys = args.empty? ? meta.keys : [args].flatten.compact
User.search do
without(:user_id, id)
any_of do
keys.each do |key|
value = meta[key]
with(key, value) if value
end
and
end
end
end
此处的性能提升非常重要。
答案 1 :(得分:3)
如果允许每个用户定义自己的属性,则一个选项可能是具有三列的表:user_id,attribute_name,attribute_value。它可能看起来像:
| user_id | attribute_name | attribute_value |
| 2 | hobbies | skiing |
| 2 | hobbies | running |
| 2 | pets | dog |
| 3 | hobbies | skiing |
| 3 | colours | green |
此表将用于查找具有相同爱好/宠物/等的其他用户。
出于性能原因(此表会变得很大),您可能希望维护信息存储的多个位置 - 用于不同目的的不同信息源。如果性能绝对必要,我不认为将相同的信息存储在多个表中是不好的。
这完全取决于您需要什么功能。也许最终会让每个用户将其键/值对序列化到users表的字符串列中(Rails为这种类型的序列化提供了很好的支持),所以当你为特定用户显示信息时你不会甚至需要触摸巨大的桌子。或许你最终会得到另一张看起来像这样的表:
| user_id | keys | values |
| 2 | hobbies, pets | skiing, running, dog |
| 3 | hobbies, colours | skiing, green |
如果您需要查找所有具有爱好的用户(针对keys列运行LIKE sql),或者与狗有任何关系的所有用户(对值列运行LIKE sql),此表将非常有用。< / p>
这是我能给出的最佳答案。也许有第三方解决方案可用,但我持怀疑态度。它并不是真正的“弹出宝石”类型的问题。
答案 2 :(得分:2)
在这种情况下,我至少会考虑像mongo或couch这样的documentdb,它可以比rdms更容易处理这种情况。
如果情况并非如此,我可能最终会按照Mike A.描述的方式做一些事情。