我有一个传入的SOAP请求,该请求试图创建或更新嵌套的资源。传入资源已经具有一个ID,我想将其用作自己的ID,而不是生成一个新ID。在继续之前,让我为您提供一些背景信息。
我有以下型号:
class AccountedTime < ApplicationRecord
belongs_to :article, optional: false
end
class Article < ApplicationRecord
has_many :accounted_times, dependent: :destroy
accepts_nested_attributes_for :accounted_times, allow_destroy: true
end
创建新资源时出现了我的问题,因此,假设在每个代码块的开头数据库都是完全空白的。我已经转换了输入数据,使其与Rails格式匹配。
# transformed incoming data
data = {
id: 1234,
title: '...',
body: '...',
accounted_times_attributes: [{
id: 12345,
units: '1.3'.to_d,
type: 'work',
billable: true,
}, {
id: 12346,
units: '0.2'.to_d,
type: 'travel',
billable: false,
}],
}
在创建非嵌套资源时,您可以提供一个ID(假设未使用),并且该ID将与提供的ID一起保存。
article = Article.find_or_initialize_by(id: data[:id])
article.update(data.except(:accounted_times_attributes))
# The above will save and create a record with id 1234.
但是,当使用update方法的接受嵌套属性接口时,上述方法不适用于嵌套资源。
article = Article.find_or_initialize_by(id: data[:id])
article.update(data)
ActiveRecord :: RecordNotFound:找不到ID = 1234的文章的ID = 12345的AccountedTime
我要实现的结果是使用提供的ID创建资源。我以为我可能忽略了提供嵌套属性时切换某种 find_or_initialize_by 或 find_or_create_by 模式的选项。我在这里想念东西吗?
我目前正在使用以下替代方法(为了简单起见,没有错误处理):
article = Article.find_or_initialize_by(id: data[:id])
article.update(data.except(:accounted_times_attributes))
data[:accounted_times_attributes]&.each do |attrs|
accounted_time = article.accounted_times.find_or_initialize_by(id: attrs[:id])
accounted_time.update(attrs)
end
答案 0 :(得分:0)
我认为您的问题不是accepts_nested_attributes_for
配置,这似乎没问题。
也许您的问题是因为您在Time
模型中使用了reserved word。尝试更改模型的名称,然后再次进行测试。
更新:
这似乎很奇怪,但是在寻找同样的问题时,我发现this answer解释了Rails 3中错误的可能原因,并给出了两种可能的解决方案。随时检查一下,希望对您有所帮助。