Ruby on rails Rails自定义元模型?
我希望能够将“元”信息添加到模型中,基本上是用户定义的字段。例如,让我们设想一个用户模型: 我为名字、姓氏、年龄、性别定义字段 我希望用户能够定义一些“元信息”,基本上进入他们的个人资料页面并共享其他信息。因此,一个用户可能想添加“嗜好”、“职业”和“家乡”,另一个用户可能想添加“嗜好”和“教育” 因此,我希望能够为这类东西提供一个标准视图,例如,在视图中,我可以做一些类似(在HAML中)的事情: 通过这种方式,我可以确保信息始终显示,而不仅仅是向用户提供一个标记文本框,用户可以使用所有不同的格式 我还希望能够点击meta并看到其他用户给出了相同的东西,因此在上面的示例中,两个用户都定义了“嗜好”,如果能够说我想看到有共同爱好的用户,那就更好了,或者我想看到嗜好为\uuuuuu的用户 所以,由于我不知道用户需要预先定义哪些字段,那么提供这种功能有哪些选项呢 有没有一个gem可以处理像这样的模型上的自定义元信息,或者至少类似的?有人遇到过这种问题吗?如果是,你是如何解决的Ruby on rails Rails自定义元模型?,ruby-on-rails,ruby-on-rails-3,metamodel,Ruby On Rails,Ruby On Rails 3,Metamodel,我希望能够将“元”信息添加到模型中,基本上是用户定义的字段。例如,让我们设想一个用户模型: 我为名字、姓氏、年龄、性别定义字段 我希望用户能够定义一些“元信息”,基本上进入他们的个人资料页面并共享其他信息。因此,一个用户可能想添加“嗜好”、“职业”和“家乡”,另一个用户可能想添加“嗜好”和“教育” 因此,我希望能够为这类东西提供一个标准视图,例如,在视图中,我可以做一些类似(在HAML中)的事情: 通过这种方式,我可以确保信息始终显示,而不仅仅是向用户提供一个标记文本框,用户可以使用所有不同的格
谢谢 如果允许每个用户定义自己的属性,一个选项可能是有一个包含三列的表:user\u id、attribute\u name、attribute\u 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 |
如果您需要查找所有有兴趣爱好的用户(针对“键”列运行类似sql),或所有与狗有关的用户(针对“值”列运行类似sql),则此表将非常有用
根据你提出的要求,这是我能给出的最好答案。也许有第三方解决方案,但我对此表示怀疑。这不是一个“弹出宝石”类型的问题。 在这种情况下,我至少会考虑像Mango或CouCh这样的文档数据库,它可以比RDMS更容易处理这种情况。
如果不是这样的话,我可能会按照Mike A.描述的思路做一些事情。动态字段的实现取决于以下因素:
用户
表
将名为meta
的text
字段添加到用户表中
更新您的用户
型号
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]}"
迭代元字段
u.meta.each do |k, v|
puts "#{k}=#{v}"
end
u = User.first
u.similar_users # matching any one of the meta fields
u.similar_users :hobbies # with matching hobbies
u.similar_users :hobbies, :city # with matching hobbies or the same city
为了满足第五个要求,您需要使用Solr或Sphinx全文搜索引擎。它们比依赖数据库进行之类的
查询更有效
这里有一种方法,如果你通过太阳黑子宝石使用Solr
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
查找类似用户
u.meta.each do |k, v|
puts "#{k}=#{v}"
end
u = User.first
u.similar_users # matching any one of the meta fields
u.similar_users :hobbies # with matching hobbies
u.similar_users :hobbies, :city # with matching hobbies or the same city
这里的性能提升非常显著。这是一个非常好的方法,我非常感谢您的分享!