无法通过关联更新has_many中的联接模型额外属性-Rails [英] Having trouble in updating join model extra attributes in has_many through association - Rails
问题描述
我仍然是Rails的学习者,并且正在制作Google Adwords模拟游戏以进行培训。在游戏内部(我只能解释这个问题的相关部分),我有三种模型:广告组(在我的代码中称为KeywordAdgroup),关键字,AdgroupKeyword ,以及
I am still a learner of Rails, and am making a simulation game of Google Adwords for training usage. Inside the game (I may only explain the related part of this question), I have three models, Adgroup (called KeywordAdgroup in my code), Keyword, AdgroupKeyword, and also a Game model that has a game_id in it.
这三个模型之间的关系是 has_many,通过:
分配,其中Adgroup通过AdgroupKeyword有很多关键字,而Adword通过AdgroupKeyword有很多广告组。
The relationship of the three models is a has_many through:
assciation, which Adgroup has many Keywords through AdgroupKeyword, and Keyword has many Adgroups through AdgroupKeyword.
现在,我想采用一种逻辑,即每个关键字只能添加到单个Adgroup中特定游戏。所以我在联接模型中添加了一个额外的属性 game_id
-AdgroupKeyword,并采用了 validates_uniqueness_of:keyword_id,范围::game_id
Now, I want to adopt a logic that every Keyword could only be added into single Adgroup of a particular game. So I added an extra attribute game_id
to the join model - AdgroupKeyword, and adopt validates_uniqueness_of :keyword_id, scope: :game_id
into this model.
但是,我发现使用类似的代码,我可以使用 .save $ c $来验证Create中的唯一性。 c>方法,但是我无法使用
.update(params)
方法验证Update中的唯一性。
However, I found that with the similar code, I can validate the uniqueness in Create using .save
method, but I can't validate the uniqueness in Update using .update(params)
method.
主要的问题是,使用 create
和 update
中的类似代码,创建的代码可以保存
game_id
到加入模型(AdgroupKeyword),其中 update(params)
没有将 game_id
保存到加入模型,在控制台中,我可以看到 update
没有
The major problem is that, with the similar code in create
and update
, the create one can save
the game_id
to the join model(AdgroupKeyword), where update(params)
didn't save the game_id
to the join model, which in the console, I can see that update
didn't insert game_id into the record.
它将变成类似 game_id:nil
:
#<AdgroupKeyword id: 180, keyword_id: 9, created_at: "2016-12-04 11:12:00", updated_at: "2016-12-04 11:12:00", keyword_adgroup_id: 77, game_id: nil>
但是save方法确实插入了game_id,当使用save方法插入时game_id并非为nil。
类似于
But the save method did insert the game_id, which game_id is not nil when inserted using the save method. Something like
#<AdgroupKeyword id: 174, keyword_id: 10, created_at: "2016-12-04 10:23:50", updated_at: "2016-12-04 10:23:50", keyword_adgroup_id: 77, game_id: 3>
以下是我的代码:
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控制器中建立关系。
And majorly the relation would be built in the Adgroup controller.
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
更新记录。
When choosing duplicate keyword in the same game in whatever adgroup, in "create", it will come to a rollback; in "update", it will just update the record with game_id: nil
.
仅供参考,我使用的是Ruby 2.3.0,Rails 5.0.0,并使用simpleform创建和更新广告组。
FYI, I am using Ruby 2.3.0, Rails 5.0.0, and using simpleform for creating and updating adgroup.
我知道它有点混乱,对此感到抱歉,并感谢您阅读我的文字。感谢任何建议。已经花了几个小时来修复它,但是在采用许多不同的方法后却真的没有希望。认为这是我尚未发现的概念问题。
I know its a little bit messy, sorry about that and thanks for reading my words. Appreciate any suggestions. Have already spent several hours to fix it but really hopeless after a lot of different methods. Thought that it was some conceptual problem that I haven't figured out.
更新后的信息
在检查控制台时,在创建方法中,它将显示为:
While checking the console, in "Create" method, it will come to:
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", #<BigDecimal:7fcaac52c320,'0.1E1',9(18)>], ["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]]
在更新方法中,它将显示为:
In "Update" method, it will come to:
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 $ c之后的之后,您是否可以尝试运行此块? $ c>调用(在
if
块内部)?
Can you try to run this block after the #update
call (inside the if
block)?
@adgroup.reload
@adgroup.adgroup_keywords.each do |join|
join.update(:game_id, @adgroup.game_id)
end
这篇关于无法通过关联更新has_many中的联接模型额外属性-Rails的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!