MySQL为INSERT
语句提供了一个非常好的选项,这对于没有id
列的连接表特别有用。它插入一条记录,但如果其密钥与现有密钥发生冲突,则不会抛出错误,而是更新该记录。这是一个例子:
INSERT INTO table (key1,key2,data) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE data=3;
如何使用Active Record实现相同目标?结果代码如下所示:
class Model < ActiveRecord::Base
belongs_to :key1
belongs_to :key2
end
record = Model.new
record.key1 = key1
record.key2 = key2
record.data = 'new data'
record.WHAT? #Inserts or updates `data` for the existing record
答案 0 :(得分:3)
j的答案是正确的想法,但您可能希望使用find_or_initialize_by来避免对对象进行多次保存。 E.g。
record = Model.find_or_initialize_by_key1_and_key2 new
record.data = 'new data'
record.save
通过它的声音,您还需要验证以检查模型是否也不允许重复连接:
class Model < ActiveRecord::Base
belongs_to :key1
belongs_to :key2
validates_uniqueness_of :key1, :scope => :key2
end
答案 1 :(得分:2)
您可以执行以下操作:
record = Model.find_or_create_by_key1_and_key2(:key1 => key1, :key2 => key2)
record.update_attribute(:data, "new data")
修改强>
zaius 的想法看起来更好,您应该使用find_or_initialize_by
来避免多次保存,正如他所说:]
答案 2 :(得分:1)
您可能需要查看composite primary keys。它是ActiveRecord的插件。
答案 3 :(得分:0)
首先,这是一个特定于MySQL的解决方案,据我所知,语法不适用于任何其他SQL服务器。通常在讨论中称为Upsert。
我要创建一个名为save_or_update
的新方法,然后如果保存失败,重复键异常,请加载update_params
。