2014-09-23 2 views
0

나는 위치와 특정 캠페인은 다음과 같은 모델 협회로 설정되어있는 카테고리를 모두 처리 할 수있는 테이블을 구축하려고 시도하고있다 :레일 액티브 : 세 개의 테이블 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 

만들려고

enter image description here

캠페인 생성 코드 : 두 개의 서로 다른 도시 및 카테고리 결과를 선택하기위한 캠페인으로 paramters 중 하나의 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 

캠페인을 만들 뷰 업데이트 등의 종류와 지하철에 대한 두 개의 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

+0

@ 에릭 다른 정보가 필요합니까? – Sauron

+1

예, campaign_params 메소드 : – Eric

답변

-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 

당신은 또한 당신의 데시벨이 제약 조건을 추가 할 수 있습니다. 그런 식으로 아무도 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 

나는 이것이 일반적으로 당신이 당신의 컨트롤러에서 캠페인 생성 코드를 추가 할 수

+0

이렇게하면 다음과 같은 상황을 예방할 수 있습니까? http://i.stack.imgur.com/u4TyA.png 행에 포함되도록 선택된 'Metros' 및'Category'의 순열을 갖고 싶습니다. 즉, 이미지에서 볼 수있는 NULL 값.'category_id'아래에 id가 9,10 인 행의 경우 NULL이 아닌 '1'및 '2'로 표시되어야합니다. – Sauron

+0

기본 외래 키는 갖고 싶지 않지만 내가 선택한 것처럼 선택할 수 있습니다. 내가 필요로하는 것은 무엇이겠습니까? – Sauron

+0

예, 우선, 좋은 검증을 받으면 나머지 코드베이스가 무엇이든간에 그런 상황이 결코 일어나지 않을 것입니다. 그것은 당신에게 일관성을 줄 것입니다. – Renra