2014-09-23 78 views
0

我试图建立一个表来处理双方的位置和类别一定的活动已被设置为以下模型协会:Rails的ActiveRecord的:三表的has_many通过:协会

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 

当试图创建选择两个不同的城市和类别的结果的活动是空的paramters之一当ID:

enter image description here

建立广告活动代号:

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 

修订 视图创建活动采用两个独立collection_select类别和地铁为:

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

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

campaigns_params:

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

有没有更好的方法来允许我尝试创建3表关系? 还是有办法使得所得表类似下面根据活动创建CategoryMetro机型在选择链接:

enter image description here

+0

你可以从你的控制器中添加广告系列创建代码的方向? – Eric 2014-09-23 01:23:41

+0

@Eric你需要其他信息吗? – Sauron 2014-09-23 01:40:33

+1

是的,你的campaign_params方法:) – Eric 2014-09-23 05:06:32

回答

-1

如果你想确保跨多个表我会验证开始数据的一致性。例如:

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 

你也可能要将此约束添加到您的数据库,如果这就是你所需要的(见迁移指南)。这样一来,没有人会破坏一致性,甚至不会从数据库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 

我希望这有助于通常设置:-)

+0

这是否有助于防止出现在这里的情况:http://i.stack.imgur.com/u4TyA.png我想要选择在行中的“Metros”和“Category”的排列,而不是可以在图像中看到NULL值。对于id为9,10的'category_id'下的行,它应该被列为'1'和'2',而不是NULL – Sauron 2014-09-23 12:49:06

+0

我不希望有任何默认外键,但允许按照我的演示进行选择。我需要的补充是什么? – Sauron 2014-09-24 02:18:48

+0

是的,首先,验证良好将确保这种情况不会再发生,无论您的代码库的其他部分如何。这会给你一致。 – Renra 2014-09-24 09:24:50