简体   繁体   English

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

[英]Having trouble in updating join model extra attributes in has_many through association - Rails

I am still a learner of Rails, and am making a simulation game of Google Adwords for training usage. 我仍然是Rails的学习者,并且正在制作Google Adwords模拟游戏以进行培训。 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. 游戏里面的(我只能说明这个问题的相关部分),我有三个型号, 广告组 (在我的代码称为KeywordAdgroup), 关键字,AdgroupKeyword,同时又有中有一个game_id博弈模型。

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. 这三种模型之间的关系是has_many through:关联,即Adgroup通过AdgroupKeyword具有许多关键字,而Adword通过AdgroupKeyword具有许多关键字。

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. 因此,我在联接模型中添加了一个额外的属性game_id -AdgroupKeyword,并在模型中采用了validates_uniqueness_of :keyword_id, scope: :game_id

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. 但是,我发现使用类似的代码,我可以使用.save方法验证Create中的唯一性,但无法使用.update(params)方法验证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. 主要问题在于,使用createupdate类似的代码,创建者可以save game_id save到联接模型(AdgroupKeyword)中,而update(params)没有将game_id保存到联接模型中(在控制台中) ,我可以看到update没有在记录中插入game_id。

It will become something like game_id: nil : 它将变成类似于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>

But the save method did insert the game_id, which game_id is not nil when inserted using the save method. 但是save方法确实插入了game_id,当使用save方法插入时game_id并非为nil。 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>

The following is my code: 以下是我的代码:

keyword_adgroup.rb (the model of Adgroup) 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 keyword.rb

class Keyword < ApplicationRecord
  ...

  ...

  has_many :keyword_adgroups, through: :adgroup_keywords
  has_many :adgroup_keywords

  ...
end

adgroup_keyword.rb (the join model) adgroup_keyword.rb联接模型)

class AdgroupKeyword < ApplicationRecord
  belongs_to :keyword_adgroup
  belongs_to :keyword

  validates_uniqueness_of :keyword_id, scope: :game_id

end

And majorly the relation would be built in the Adgroup controller. 关系主要建立在Adgroup控制器中。

adgroups_controller.rb 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

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 . 在“更新”中,它将仅使用game_id: nil更新记录。

FYI, I am using Ruby 2.3.0, Rails 5.0.0, and using simpleform for creating and updating adgroup. 仅供参考,我正在使用Ruby 2.3.0,Rails 5.0.0,并使用simpleform创建和更新广告组。

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. 认为这是我尚未弄清楚的一些概念性问题。


Updated Information 更新信息

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]]

Can you try to run this block after the #update call (inside the if block)? 你可以尝试运行后,该块#update调用(内if块)?

@adgroup.reload

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Rails has_many:通过在联接模型中按附加属性查找 - Rails has_many :through Find by Extra Attributes in Join Model 如何在has_many中获取模型的属性:通过Rails 5中的关联 - How to get attributes of model in has_many :through association in Rails 5 具有has_many的模型中属性的总和:通过关联在Rails 5中不起作用 - Sum of attributes in model with has_many :through association not working in Rails 5 使用Rails更新has_many,:through关系中的额外属性 - Updating extra attributes in a has_many, :through relationship using Rails 遇到has_many问题:通过关联 - Having trouble with has_many :through association Rails 4 + Pundit:在has_many中加入模型授权:通过关联 - Rails 4 + Pundit : join model authorization in has_many :through association rails 3.1 has_many:通过加入模型中的额外字段 - rails 3.1 has_many :through extra field in join model 在rails has_many中使用join模型属性:through - using join model attributes in rails has_many :through 通过关联将额外字段添加到has_many中的联接表中 - Adding an extra field to the join table in has_many through association 通过以下方式在has_many上优雅地设置联接表属性: - Elegantly set join table attributes on has_many through: association
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM