7

我有一个SaaS应用程序,帐户想要在用户模型上保存不同类型的信息。例如,一个帐户可能希望保存年龄和生日,但在另一个帐户中,他们不会使用这些列,并且希望保存关于头发颜色和身高的信息。Rails:模型上的动态列/属性?

这些仅仅是一些例子,但我如何构建我的模型和数据库,以便它可以很好地适用于“定制的,动态的”列而不会创建太多的空属性。

+0

jc,你最终会在哪里用这个? – mmcrae 2015-03-04 14:52:40

+1

@mmcrae我结束了使用postgresql的.json数据结构,并将任何自定义列转储到此.json数据字段中。 – kibaekr 2015-03-05 09:37:43

回答

5

对我来说,这个声音就像一个完美的例子,你想使用一个无模式的NoSQL数据库。或者(如果你想坚持SQL),你可以有一个基地User模型与has_many :attributes协会。其中一个属性只是key('年龄','生日','头发颜色')和一个值的组合。复杂性来自不同的数据类型和同时涉及多个属性的查询。

0

你的模式可能是这样的:

create_table "accounts", :force => true do |t| 
    t.integer "user_id" 
    t.string "data_key" 
    t.string "data_value" 
end 

Account模型

belongs_to :user  
DATA_KEYS = ['age', 'birthdate', 'hair_color', 'height' ] # etc.. 

用户模型

has_many :accounts 
Account::DATA_KEYS.each do |method| 
    # getter method 
    define_method(method) do 
    accounts.find_by_data_key(method).try(:data_value) 
    end 

    # setter method 
    define_method("#{method}=") do |value| 
    data = accounts.find_or_initialize_by_data_key(method) 
    data.data_value = value.strip 
    data.save 
    end 
end 

您可以获取和设置帐户数据值

例如user.age =>将返回的用户年龄

user.hair_color = 'brown' =>将设置头发的颜色

+0

如果用户属于多个帐户,此代码是否会更改?并且帐户会选择他们是否想要支持某个data_key,并且该帐户中的用户将拥有这些data_keys上的data_values – kibaekr 2014-09-26 00:29:42

+0

我收到此错误:“NoMethodError:undefined method find_by_data_key for#” – kibaekr 2014-09-26 04:30:33

+0

@ kibaekr,用户模型具有'has_many:accounts'并且'find_by_data_key'方法不是针对'User'对象,而是针对'Account'模型。 – shweta 2014-09-26 05:08:56

0

我建议去一个的NoSQL数据库。它们是专门为这种情况设计的,所以你不必为了工作而做疯狂的事情。 MongoDB结合MongoID是一个非常稳固的解决方案。

唯一的缺点可能是托管,因为它往往是轻微的,至少,更昂贵。

7

以下是两个选项。 1. NoSQL数据库。 2. Rails 4 Store功能。

+1

Rails Store看起来非常有趣,适用于许多您希望坚持使用常用数据库和模型的情况,以及“当您不关心能够在单个记录的上下文之外查询该商店时” - 引用文档。适合我。 – DannyB 2015-12-16 12:21:12

1

如果你使用PostgreSQL,你可以看看hstore那么你可以保存信息序列化,实际上你可以对这些哈希一些疑问BTW轨道4,5已经包括此功能,但如果您使用的是旧版本的Rails你可以包含这个宝石。 https://github.com/diogob/activerecord-postgres-hstore在你的Gemfile中,你应该可以像下面这样开始播放:

user = User.new 
user.preferences = { 
    email: "[email protected]", 
    github: "heridev" 
} 

user.save! 
user.reload 

# Searching 
User.where("preferences @> hstore(:key, :value)", key: "email", value: "[email protected]").first