【问题标题】:Rails: dynamic columns/attributes on models?Rails:模型上的动态列/属性?
【发布时间】:2014-11-19 16:51:18
【问题描述】:

我有一个 SaaS 应用程序,其中帐户想要在用户模型上保存不同类型的信息。例如,一个帐户可能想要保存年龄和出生日期,但在另一个帐户中,他们不会使用这些列,而是希望保存有关头发颜色和身高的信息。

这些只是示例,但我将如何构建我的模型和数据库,以便它可以很好地与“自定义、动态”列一起使用,而不会创建太多空属性。

【问题讨论】:

  • jc,你最后去哪儿了?
  • @mmcrae 我最终使用了 postgresql 的 .json 数据结构,并将任何自定义列转储到这个 .json 数据字段中。

标签: ruby-on-rails ruby database ruby-on-rails-4 database-design


【解决方案1】:

这里有两个选项。 1. NoSQL 数据库。 2.Rails 4 Store功能。

【讨论】:

  • Rails Store 看起来真的很有趣,并且适用于许多你想坚持使用常用数据库和模型的情况,以及“当你不关心能够在单一记录” - 引用文档。非常适合我。
【解决方案2】:

对我来说,如果您想使用无模式 NoSQL 数据库,这听起来像是一个完美的例子。

或者(如果你想坚持使用 SQL)你可以有一个基本的 User 模型与 has_many :attributes 关联。其中属性只是key('年龄'、'生日'、'头发颜色')和值的组合。复杂性来自于同时涵盖多个属性的不同数据类型和查询。

【讨论】:

    【解决方案3】:

    如果您使用的是 Postgresql,您可以查看 hstore,然后您可以保存序列化的信息,实际上您可以对这些哈希进行一些查询,顺便说一下 Rails 4 包含此功能,但如果您使用的是旧版 Rails,您可以包括这个宝石。 https://github.com/diogob/activerecord-postgres-hstore 在你的 Gemfile 中,你应该可以开始玩了:

    user = User.new
    user.preferences = {
      email: "p@elh.mx",
      github: "heridev"
    }
    
    user.save!
    user.reload
    
    # Searching
    User.where("preferences @> hstore(:key, :value)", key: "email", value: "p@elh.mx").first
    

    【讨论】:

      【解决方案4】:

      如果您想继续使用关系数据库,请为此制作一个宝石

      https://github.com/Liooo/dynabute

      【讨论】:

        【解决方案5】:

        您的架构可能是这样的:

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

        帐户模型

        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' => 将设置头发颜色

        【讨论】:

        • 如果用户属于多个帐户,此代码是否会发生变化? Accounts 会选择是否支持某个 data_key,并且该帐户中的用户将在这些 data_keys 上拥有 data_values
        • 我收到此错误:“NoMethodError: undefined method `find_by_data_key' for #<0x00000109a7da00>
        【解决方案6】:

        我建议使用 NoSQL 数据库。它们专为此类情况而设计,因此您不必做疯狂的事情来使事情正常进行。 MongoDB 结合MongoID 是一个非常可靠的解决方案。

        唯一的缺点可能是托管,因为它往往会稍微贵一些,至少贵一些。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-17
          相关资源
          最近更新 更多