我希望一个对象具有多个可扩展的属性?如何使用activerecord实现这一目标?

时间:2011-10-18 16:44:22

标签: ruby-on-rails activerecord associations

我需要一个具有许多属性的对象User。我需要能够动态创建和添加属性,并且能够以正常方式轻松访问这些属性。

实现这一目标的最佳方法是什么?

为清楚起见 - 这是我想要创建的东西的类型:

User.name = "Dave"
User.type = "Admin"
User.height = 12
User.weight = 2
User.favourite_beer = "IPA"

User.name = "Shelly"
User.type = "Admin"
User.height = 12
User.weight = 2
User.favourite_makeup = "Lipstick"

这是为了表明Shelly会有一个favourite_makeup,而Dave不会,因为它不适用。

我知道我可以简单地在表中将favourite_makeup设置为null - 但我不想最终得到一个效率很低的表,因为可能有很多属性。

为粗略的例子道歉。

谢谢:)

3 个答案:

答案 0 :(得分:2)

您可能想尝试序列化

http://api.rubyonrails.org/classes/ActiveRecord/Base.html - 在文本列中保存数组,哈希和其他不可映射的对象

class User < ActiveRecord::Base
    serialize :preferences, Hash
end

u = User.new
u.preferences[:favourite_beer] = "IPA"

您的表格中会有一个名为“首选项”或“收藏夹”的文本列或其他

答案 1 :(得分:0)

我不确定模型设置但是对于数据库设置我会做这样的事情:

class CreateEntities < ActiveRecord::Migration
  def self.up
    create_table :entities do |t|
      t.text :entity

      t.timestamps
    end
  end

  def self.down
    drop_table :entities
  end
end

class CreateAttributes < ActiveRecord::Migration
  def self.up
    create_table :attributes do |t|
      t.integer :entity_id
      t.integer :user_id
      t.text :value

      t.timestamps
    end
  end

  def self.down
    drop_table :attributes
  end
end

想法是“favourite_beer”和“favourite_makeup”将是实体,然后属性将是您将实体和用户关联的位置,并且保存值。这样你就可以拥有多对多的东西。

从这里你可能想要做 用户

has_many :attributes
has_many :entities, :through => attributes

实体

has_many :attributes

属性

has_many :entities
has_many :users

我对模特等并不是100%肯定,但这应该足以让你开始或让其他人落后并填补空白。

答案 2 :(得分:0)

你想要db还是类?

<强> DB:
为用户创建一个表(ID,名称等)
创建属性定义表(ID,属性,类型)
为具有属性(UserID,AttributeID,Value)

的链接用户创建表

示例:

用户

1 |用户1
2 |用户2

属性

1 | Attribute1 |字符串
2 | Attribute2 |字符串
3 |属性3 | INT

UserAttributes

1 | 1 |值1
1 | 2 |值2
2 | 2 |值3
2 | 3 | VALUE4

说明:

  • User1的Attribute1为Value1
  • User1的Attribute2为Value2
  • User2的Attribute2为Value3
  • User2的Attribute3为Value4

<强>类: 这只是一个想法

Public Class User
    Private ReadOnly innerList As Dictionary(Of String, Object)

    Public Default Property Item(index As String) As Object
        Get
            If innerList.ContainsKey(index) Then
                Return innerList(index)
            End If
            Throw New IndexOutOfRangeException
        End Get
        Set(value As String)
            If innerList.ContainsKey(index) Then
               innerList(index)=value
            Else
                innerList.Add(index,value)
            End If
        End Set
    End Property

    Public sub Add(index As String,value As Object) 
        If innerList.ContainsKey(index) Then
            innerList(index)=value
        Else
            innerList.Add(index,value)
        End If
    End Sub

    Public Sub test
        Dim u1 As new User
        Dim u2 As New User
        u1.Add("attribute1","value1")
        u1.Add("attribute2","value2")
        u2.Add("attribute2","value3")
        u2.Add("attribute3","value4")
        Dim att1 As String=u1("attribute1").ToString
        Dim att3 As String=u2.Item("attribute3").ToString
    End Sub

End Class

希望这对你有所帮助。