无法通过关联更新has_many中的连接模型额外属性 – Rails

我仍然是Rails的学习者,正在制作一个Google Adwords模拟游戏,用于培训。 在游戏内部(我可能只解释这个问题的相关部分),我有三个模型,Adgroup(在我的代码中称为KeywordAdgroup), Keyword,AdgroupKeyword ,以及其中包含game_id的游戏模型。

这三种模式之间的关系是一个很好的结果has_many through: assciation,Adgroup通过AdgroupKeyword有很多关键字,而Keyword通过AdgroupKeyword有很多Adgroups。

现在,我想采用一种逻辑,即每个关键字只能添加到特定游戏的单个广告组中。 所以我在连接模型中添加了额外的属性game_id – AdgroupKeyword,并在此模型中采用validates_uniqueness_of :keyword_id, scope: :game_id

但是,我发现使用类似的代码,我可以使用.save方法validationCreate中的唯一性,但我无法使用.update(params)方法validationUpdate中的唯一性。

主要问题是,使用createupdate的类似代码,create one可以save game_id save到连接模型(AdgroupKeyword),其中update(params)没有将game_id保存到连接模型,在控制台中,我可以看到update没有将game_id插入记录中。

它会变成像game_id: nil

 # 

但是save方法确实插入了game_id,当使用save方法插入时,game_id不是nil。 就像是

 # 

以下是我的代码:

keyword_adgroup.rb (广告组的模型)

 class KeywordAdgroup < ApplicationRecord belongs_to :keyword_campaign has_many :adgroup_keywords, inverse_of: :keyword_adgroup, dependent: :destroy has_many :keywords, through: :adgroup_keywords, source: :keyword accepts_nested_attributes_for :adgroup_keywords, allow_destroy: true ... accepts_nested_attributes_for :keywords ... ... end 

keyword.rb

 class Keyword < ApplicationRecord ... ... has_many :keyword_adgroups, through: :adgroup_keywords has_many :adgroup_keywords ... end 

adgroup_keyword.rb (连接模型)

 class AdgroupKeyword < ApplicationRecord belongs_to :keyword_adgroup belongs_to :keyword validates_uniqueness_of :keyword_id, scope: :game_id end 

主要是关系将建立在Adgroup控制器中。

adgroups_controller.rb

 class Adwords::AdgroupsController < AdwordsController def index ... end def new @adgroup = KeywordAdgroup.new end def create @campaign = current_user.game.keyword_campaigns.find(params[:keyword_campaign_id]) @adgroup = @campaign.keyword_adgroups.build(adgroup_params) @adgroup.game_id = @campaign.game_id @adgroup.adgroup_keywords.each do |join| join.game_id = @adgroup.game_id end if @adgroup.save redirect_to new_adwords_ad_path(keyword_adgroup_id: @adgroup.id) else render :new end end def edit @adgroup = KeywordAdgroup.find(params[:id]) end def update @adgroup = KeywordAdgroup.find(params[:id]) @campaign = @adgroup.keyword_campaign @adgroup.game_id = @campaign.game_id @joins = @adgroup.adgroup_keywords @joins.each do |join| join.game_id = @adgroup.game_id end if @adgroup.update(adgroup_params) redirect_to adwords_adgroups_path, notice: "Adgroup updated" else render :edit end end ... private def adgroup_params params.require(:keyword_adgroup).permit(:name, :activate, :bid, keyword_ids: [], adgroup_keywords_attributes: [:game_id]) end end 

当在任何广告组中的同一游戏中选择重复关键字时,在“创建”中,它将进行回滚; 在“更新”中,它将使用game_id: nil更新记录。

仅供参考,我使用Ruby 2.3.0,Rails 5.0.0,并使用simpleform创建和更新adgroup。

我知道它有点乱,抱歉,感谢阅读我的话。 感谢任何建议。 已经花了几个小时来修复它,但在经过许多不同的方法之后真的没有希望。 认为这是一些我没想到的概念性问题。


更新的信息

检查控制台时,在“创建”方法中,它将来:

  AdgroupKeyword Exists (0.4ms) SELECT 1 AS one FROM "adgroup_keywords" WHERE "adgroup_keywords"."keyword_id" = ? AND "adgroup_keywords"."game_id" = ? LIMIT ? [["keyword_id", 14], ["game_id", 3], ["LIMIT", 1]] Keyword Exists (0.3ms) SELECT 1 AS one FROM "keywords" WHERE "keywords"."keyword" = ? AND ("keywords"."id" != ?) LIMIT ? [["keyword", "Japan local trip"], ["id", 14], ["LIMIT", 1]] KeywordAdgroup Exists (0.2ms) SELECT 1 AS one FROM "keyword_adgroups" WHERE "keyword_adgroups"."name" = ? AND "keyword_adgroups"."keyword_campaign_id" = ? LIMIT ? [["name", "3"], ["keyword_campaign_id", 36], ["LIMIT", 1]] SQL (2.3ms) INSERT INTO "keyword_adgroups" ("name", "activate", "bid", "created_at", "updated_at", "keyword_campaign_id", "game_id") VALUES (?, ?, ?, ?, ?, ?, ?) [["name", "3"], ["activate", true], ["bid", #], ["created_at", 2016-12-04 13:10:19 UTC], ["updated_at", 2016-12-04 13:10:19 UTC], ["keyword_campaign_id", 36], ["game_id", 3]] SQL (0.2ms) INSERT INTO "adgroup_keywords" ("keyword_id", "created_at", "updated_at", "keyword_adgroup_id", "game_id") VALUES (?, ?, ?, ?, ?) [["keyword_id", 14], ["created_at", 2016-12-04 13:10:19 UTC], ["updated_at", 2016-12-04 13:10:19 UTC], ["keyword_adgroup_id", 84], ["game_id", 3]] AdgroupKeyword Exists (0.3ms) SELECT 1 AS one FROM "adgroup_keywords" WHERE "adgroup_keywords"."keyword_id" = ? AND ("adgroup_keywords"."id" != ?) AND "adgroup_keywords"."game_id" = ? LIMIT ? [["keyword_id", 14], ["id", 187], ["game_id", 3], ["LIMIT", 1]] 

在“更新”方法中,它将来:

  AdgroupKeyword Exists (0.2ms) SELECT 1 AS one FROM "adgroup_keywords" WHERE "adgroup_keywords"."keyword_id" = ? AND "adgroup_keywords"."game_id" IS NULL LIMIT ? [["keyword_id", 17], ["LIMIT", 1]] SQL (2.0ms) INSERT INTO "adgroup_keywords" ("keyword_id", "created_at", "updated_at", "keyword_adgroup_id") VALUES (?, ?, ?, ?) [["keyword_id", 17], ["created_at", 2016-12-04 13:07:03 UTC], ["updated_at", 2016-12-04 13:07:03 UTC], ["keyword_adgroup_id", 82]] AdgroupKeyword Exists (0.2ms) SELECT 1 AS one FROM "adgroup_keywords" WHERE "adgroup_keywords"."keyword_id" = ? AND ("adgroup_keywords"."id" != ?) AND "adgroup_keywords"."game_id" = ? LIMIT ? [["keyword_id", 11], ["id", 185], ["game_id", 3], ["LIMIT", 1]] 

你可以尝试在#update调用之后运行这个块(在if块内)吗?

 @adgroup.reload @adgroup.adgroup_keywords.each do |join| join.update(:game_id, @adgroup.game_id) end