Rails ActiveRecord:三个表 has_many 通过:关联

2024-01-30

我正在尝试构建一个表来处理某个营销活动已设置为的位置和类别,并具有以下模型关联:

class Campaign < ActiveRecord::Base

    has_many :campaign_category_metro_bids, dependent: :destroy
    has_many :metros,     through: :campaign_category_metro_bids
    has_many :categories, through: :campaign_category_metro_bids

end

class Metro < ActiveRecord::Base

    has_many :campaign_category_metro_bids
    has_many :campaigns,  through: :campaign_category_metro_bids
    has_many :categories, through: :campaign_category_metro_bids

end

class Category < ActiveRecord::Base

    has_many :campaign_category_metro_bids
    has_many :campaigns,  through: :campaign_category_metro_bids
    has_many :metros,     through: :campaign_category_metro_bids

end

class CampaignCategoryMetroBid < ActiveRecord::Base
    belongs_to :campaign
    belongs_to :category
    belongs_to :metro
end

当尝试创建一个选择两个不同城市和类别的营销活动时,其中一个参数的 id 结果为 NULL,如下所示:

活动创建代码:

def new
    if signed_in?
        # create new campaign
        @user = User.find(params[:id])
        @campaign = @user.campaigns.new
    else
        redirect_to signin_path
    end
end

def create
    @campaign = User.find(params["campaign"]["user_id"]).campaigns.build(campaign_params)

    if @campaign.save
        flash[:success] = "Campaign created!"
        redirect_to current_user
    else
        render 'new'
    end
end

UPDATED创建营销活动的视图对 Category 和 Metro 使用两个单独的 collection_select ,如下所示:

        <%= f.collection_select :category_ids, Category.all, :id, :display_category, {}, {multiple: true} %>

and

    <%= f.collection_select :metro_ids, Metro.all, :id, :full_name, {}, {multiple: true} %>

活动参数:

    def campaign_params
        params.require(:campaign).permit(:name, :campaign_category_metro_bid_id,
                                         :metro_ids => [], :category_ids => [])
    end

当我尝试时,是否有更好的方法来允许创建 3 个表关系? 或链接的方式Category and Metro选择模型,以便在创建活动时生成的表格如下所示:


如果您想确保多个表之间的数据一致性,我将从验证开始。例如:

class CampaignCategoryMetroBid < ActiveRecord::Base
  belongs_to :campaign
  belongs_to :category
  belongs_to :metro

  validates :campaign, presence: true
  validates :category, presence: true
  validates :metro, presence: true
end

如果您需要的话,您可能还想将此约束添加到您的数据库中(请参阅迁移指南)。这样就没有人能够破坏一致性,即使是从 db cli 也不行。现在,每次您的代码尝试创建不带外键的 CampaignCategoryMetroBid 实例时,ActiveRecord 都会喊叫并限制其余代码的“行为”。

如果您确实只想注入一些默认外键(或以其他方式调整表单数据),您可以在控制器操作中预处理表单数据时执行此操作。例如:

class CampaignsController < ActionController::Base
   def create

     # Possibly refactor to a before_action
     if params[:campaign] && params[:capmaign][:metro_ids] && params[:capmaign][:metro_ids].empty?
       params[:campaign][:metro_ids] = [DEFAULT_CAMPAIGN_ID]
     end

     # Do the rest
   end
end

我希望这有助于总体确定方向:-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rails ActiveRecord:三个表 has_many 通过:关联 的相关文章

随机推荐