2016-12-04 14 views
0

Я все еще участвую в Rails и делаю имитационную игру Google Adwords для обучения. Внутри игры (я могу только объяснить связанную часть этого вопроса) у меня есть три модели: Группа (называемая ключевой группой в моем коде), Ключевое слово, AdgroupKeyword, а также игровая модель, в которой есть game_id.У вас возникли проблемы с обновлением дополнительных атрибутов в has_many через ассоциацию - Rails

Отношения трех моделей: has_many through: assciation, в которой у Adgroup есть много ключевых слов через AdgroupKeyword, а Keyword имеет много Adgroups через AdgroupKeyword.

Теперь я хочу принять логику, что каждое ключевое слово может быть добавлено только в единую группу определенных игр. Поэтому я добавил дополнительный атрибут game_id в модель объединения - AdgroupKeyword и применил validates_uniqueness_of :keyword_id, scope: :game_id в эту модель.

Однако, я нашел, что с аналогичным кодом я могу проверить уникальность в Create с помощью метода .save, но я не могу проверить уникальность в Update с помощью метода .update(params).

Основная проблема заключается в том, что, с аналогичным кодом в create и update, то создать можно save в game_id к модели присоединиться (AdgroupKeyword), где update(params) не спасти game_id модели присоединиться, которая в консоль, я вижу, что update не вставлял game_id в запись.

Это будет что-то вроде 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> 

Но метод сохранения сделал вставить game_id, который game_id не является нулевым при вставке с использованием метода сохранения. Что-то вроде

#<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 (модель Adgroup)

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.

FYI, я использую Ruby 2.3.0, Rails 5.0.0 и используя simpleform для создания и обновления группы объявлений.

Я знаю его немного грязно, жаль об этом и спасибо за чтение моих слов. Оцените любые предложения. Уже потратили несколько часов, чтобы исправить это, но действительно безнадежно после множества разных методов. Думал, что это была какая-то концептуальная проблема, которую я не понял.


Обновление информации

При проверке консоли, в методе "Создать", он придет к:

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

В методе "Update", он придет к:

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

ответ

0

Можете ли вы попытаться запустить этот блок после#update звонок (внутри блока if)?

@adgroup.reload 

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

О, вы правы, coz в моем «создании», он должен был сделать первый шаг на выборе кампании ключевого слова, следовательно, передать campaign_id и создать группу объявлений. Но почему и как это повлияет на мой метод «обновления»? Большое спасибо! –

+0

Я только что обновил свой ответ - можете ли вы проверить, действительно ли он передает значение 'game_id'? –

+0

Спасибо, я обновил некоторую информацию внизу. Я пытался удалить его из разрешенных параметров раньше, но не повезло. Чувствуйте себя смущенным в течение нескольких часов. –