2013-05-10 64 views
0

Ruby的新手在这里。首先,这比实际更具哲理性,所以如果有更好的方法来实现这一点,请告诉。遍历数据库记录创建属性哈希

我有一个表,看起来大致是:

╔════╦════════╦════════╦══════════╗ 
║ ID ║ label ║ value ║ thing_id ║ 
╠════╬════════╬════════╬══════════╣ 
║ 1 ║ color ║ red ║  1 ║ 
║ 2 ║ size ║ medium ║  1 ║ 
║ 3 ║ weight ║ heavy ║  1 ║ 
╚════╩════════╩════════╩══════════╝ 

我查询此并获得一个特定的事物的记录。

thing_attributes = ThingAttributes.where(:thing_id => 1) 

这导致该表中有5行左右的记录集。我希望能够创建一个允许我创建{"color" => "red", "size" => "medium", "weight" => "heavy" }的等效项目。思考?

+0

你能澄清你的问题。我对你的措辞感到困惑。 – jason328 2013-05-10 19:50:31

+0

对不起。我认为我的头衔可能是错误的。我会尽力澄清。 – netricate 2013-05-10 19:58:18

+0

你想要这个散列究竟是什么?每个记录标签的汇总?该表应该是一个统一的散列图吗?我的意思是,如果你有50条记录,你想要一个有50个键和50个值的散列吗?你会接受多个具有相同标签(密钥)的记录吗? – 2013-05-10 20:20:07

回答

2

好了,基本上你想模仿无模式数据库,因为您希望不同的记录具有不同的属性。只要你只有一个自定义属性pr。记录,这可能是工作,但如果你的记录有差异比一般多个属性,那么你可能要考虑有多种型号,看看到hstore数据类型或寻找到一个文件数据库,如MongoDB的。

更新

重读你的问题,我想我有一个更好的解决办法,所以我删除了原来的一个。

我会打电话给你ThingAttributes类什么,我认为这是 - 一个CustomAttribute类。因为每个记录代表一个自定义属性。事物可以有许多(在你的例子中是五个)自定义属性。

所以,你可以这样做:

class CustomAttribute < ActiveRecord::Base 
    belongs_to :thing 
    attr_accessible :name, :value 
end 

class Thing < ActiveRecord::Base 
    has_many :custom_attributes 
end 

现在你可以找到一个东西,写

my_thing = Thing.find(3) 

然后你可以找到它的custom_attributes,通过写

my_thing.custom_attributes 

这将返回一组自定义属性。然而,你是(出于某种原因)要求散列。这也可以做到。在您的Thing类中,定义此方法:

def custom_attributes_hash 
    custom_hash = {} 
    self.custom_attributes.each do |attr| 
    custom_hash[attr.name] = attr.value 
    end 
    custom_hash 
end 

现在,您可能希望能够以便捷的方式设置属性。在你的课堂上定义这个。

def set_custom_attribute(name, value) 
    return unless name.present? # Short circuits method if an empty string or nil is being used as name. 
    custom_attribute = self.custom_attributes.find_by_name(name) # Attemps to find custom attribute with the name 
    if custom_attribute.nil? # Executes block if no attribute was found 
    return unless value.present? # Short circuits method if nil or empty string was passed as value 
    self.custom_attributes.create(name: name, value: value) # Creates and saves new custom attribute 
    else 
    if value.present? # Updates existing attribute if passed is not an empty string or nil. 
     custom_attribute.update_attribute(:value, value) 
    else 
     custom_attribute.destroy # Deletes custom attribute from DB if set_custom_attribute was called with a nil or empty value. 
    end 
    end 
end 
+0

这看起来像我应该做的。非常感谢!(特别是在我重读了我的问题之后,真的很尴尬地问过它 - 你得到了我之后的结果) – netricate 2013-05-10 20:09:19

+0

我编辑了答案,因为我忘记了Ruby不支持重载。你可以有一个attr方法,它既是一个getter也是一个setter(第二个参数是可选的),但它有一些缺陷。 – 2013-05-10 20:13:04

+0

我已经读过你的问题了,我不认为我的解决方案会起作用,因为你不会得到你要求的散列。相反,您将获得一组记录,每个记录都有自己的属性。通过调用标签访问器,您将能够确定该记录的任何自定义属性,但效果不佳。我会编辑一个更好的解决方案的答案。 – 2013-05-10 20:26:26

0

我不知道如果我越来越好,但试试这个:

my_thing = Thing.find(1) 
my_thing.color 
0

我觉得这是你在问什么:

Thing_model.rb 

thing = Thing.find(1) 

def #{self.label} 
    return self.value