设置
我有两个模型:Language
和LanguageCode
,它们看起来如下:
一种语言可以有多种语言代码。
class Language < ApplicationRecord
has_many :language_codes
accepts_nested_attributes_for :language_codes, allow_destroy: true, reject_if: :reject_empty
def reject_empty(attributes)
attributes['id'].blank?
end
end
class LanguageCode < ApplicationRecord
belongs_to :language, optional: true
end
LanguageCode
s是独立于Language
s创建的。例如,代码en_us
应该分配给English
,等等。与指南相反,LanguageCode
可以存在于Language
之外,也可以改变关联,分配给另一种语言。
我使用一个嵌套的for和一个collection_select
,它显示了所有可用的LanguageCodes
,即那些还没有赋值的和那些已经赋值的。
控制器更新方法如下所示:
class LanguagesController < BaseController
# Save updates to database.
def update
# Find language by id, code omitted
lang = params.require(:language).permit(:label, language_codes_attributes: [:id, :_destroy])
@language.update(lang)
# The rest of the method
# ...
end
end
问题
每当我从下拉列表中选择一种语言时,@language.update
就会失败。原因是它试图根据:id
和:language_id
执行查找,而后者没有设置。这是因为代码还没有与语言相关联,因此数据库中没有设置belongs_to
id。
我的问题是:嵌套属性可以用这种方式使用吗?或者它们的唯一目的是具有固定的关联,如:一个Language
有一个Code
,代码总是属于同一种语言?
尝试的解决方案
我的解决办法很简单:在控制器中,读取update
上的所有嵌套属性,通过id更新每个LanguageCode并手动设置belongs_to。这可能看起来像这样,它应该可以正常工作:
def update
@language = Language.find(params[:id])
params[:language][:language_codes_attributes].each do |attr|
LanguageCode.find(attr[:id]).update(language: @language)
end
# Rest of the method
end
1条答案
按热度按时间ylamdve61#
我不知道你在表单中用collection_select做了什么。但对于这种情况,有
language_code_ids
方法:确保允许它:
.permit(language_code_ids: [])
。一切都应该自己工作。accepts_nested_attributes_for
不需要。只有更新,没有删除。