ruby-on-rails Rails 7:更改嵌套属性的关联

mctunoxg  于 2023-04-13  发布在  Ruby
关注(0)|答案(1)|浏览(139)

设置

我有两个模型:LanguageLanguageCode,它们看起来如下:
一种语言可以有多种语言代码。

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
ylamdve6

ylamdve61#

我不知道你在表单中用collection_select做了什么。但对于这种情况,有language_code_ids方法:

<%= f.collection_check_boxes :language_code_ids, LanguageCode.all, :id, :code %>

确保允许它:.permit(language_code_ids: [])。一切都应该自己工作。accepts_nested_attributes_for不需要。

>> Language.first.language_code_ids
  Language Load (0.1ms)  SELECT "languages".* FROM "languages" ORDER BY "languages"."id" ASC LIMIT ?  [["LIMIT", 1]]
  LanguageCode Pluck (0.1ms)  SELECT "language_codes"."id" FROM "language_codes" WHERE "language_codes"."language_id" = ?  [["language_id", 1]]
=> [3]

>> Language.first.language_code_ids = [1,2]
  Language Load (0.2ms)  SELECT "languages".* FROM "languages" ORDER BY "languages"."id" ASC LIMIT ?  [["LIMIT", 1]]
  LanguageCode Load (0.3ms)  SELECT "language_codes".* FROM "language_codes" WHERE "language_codes"."id" IN (?, ?)  [["id", 1], ["id", 2]]
  LanguageCode Load (0.1ms)  SELECT "language_codes".* FROM "language_codes" WHERE "language_codes"."language_id" = ?  [["language_id", 1]]
  TRANSACTION (0.1ms)  begin transaction
  LanguageCode Update All (0.2ms)  UPDATE "language_codes" SET "language_id" = ? WHERE "language_codes"."language_id" = ? AND "language_codes"."id" = ?  [["language_id", nil], ["language_id", 1], ["id", 3]]
  LanguageCode Update (0.1ms)  UPDATE "language_codes" SET "language_id" = ? WHERE "language_codes"."id" = ?  [["language_id", 1], ["id", 1]]
  LanguageCode Update (0.1ms)  UPDATE "language_codes" SET "language_id" = ? WHERE "language_codes"."id" = ?  [["language_id", 1], ["id", 2]]
  TRANSACTION (6.5ms)  commit transaction
=> [1, 2]

只有更新,没有删除。

相关问题