好的,我正在开始规范化我的数据库。目前我有一个型号“产品”,通过数据源(XML)填充了大约60,000种产品,其中包含带有类别名称和商家名称的产品。我想将它们分成3个模型;产品,类别和商家。
每个产品都有一个类别和一个商家,所以自然的想法就是创建这些模型:
category_id | CATEGORY_NAME
merchant_id | MERCHANT_NAME
我可以计算出模型之间关联的代码,例如has_one,belongs_to等,但我正在努力自动将新产品与类别和商家以编程方式关联。
我已经看过书中的例子,你的数据库开头是空的,看起来非常简单。但是,我从一个完整的数据库和一个类别名称列表开始。
这是我的产品创建声明,它非常有效:
Product.create(:name => node.xpath("./text/name/text()").inner_text.downcase,
:description => node.xpath("./text/desc/text()").inner_text,
:brand => node.xpath("./brand/text()").inner_text,
:merchant => node.xpath("../@name").inner_text,
:category => node.xpath("./cat/text()").inner_text.downcase,
:price => "£" + node.xpath("./price/btext()").inner_text)
我需要做这样的事情,请参阅:类别行,(我知道以下是错误的btw!)...
Product.create(:name => node.xpath("./text/name/text()").inner_text.downcase,
:description => node.xpath("./text/desc/text()").inner_text,
:brand => node.xpath("./brand/text()").inner_text,
:merchant => node.xpath("../@name").inner_text,
:category => << Category.find_by_name(node.xpath("./cat/text()").inner_text.downcase),
:price => "£" + node.xpath("./price/btext()").inner_text)
有什么想法吗?这甚至有意义吗??
答案 0 :(得分:1)
假设这些列名为category_name
和merchant_name
,并且您已在Category
和Merchant
上设置关联,则可以执行以下操作:
Product.all do |product|
product.category = Category.find_or_create_by_category_name(product.category_name)
product.merchant = Merchant.find_or_create_by_merchant_name(product.merchant_name)
product.save!
end
这需要一段时间,因此对于大型数据集,您可能需要更好的解决方案。
那么这实际上会将products表中的:category值设置为category_id还是将值设置为category_name?
.find_or_create_by
查找属性并返回匹配的行,如果不存在则创建一个。通过`.category =创建关联时,Rails将设置外键以匹配类别表中行的id。
所以更直接地回答你的问题:
Product.create(:category=>Category.find_or_create_by_name("Magic Beans"))
就像这样:
category = Category.find_by_name("Magic Beans")
if category.nil?
category = Category.create(:name=>"Magic Beans")
end
product = Product.new
product.category = category
product.save
其中倒数第二步将外键category_id
设置为值category.id
。按照惯例,设置关联,使得外键是带有_id
后缀的型号名称,因此您的产品表应同时包含category_id
和merchant_id
。