2013-02-26 54 views
2

我有這個模型關係返回false,則不能將產品添加到一個的has_many:通過

class User < ActiveRecord::Base 
    has_many :trip_memberships, dependent: :destroy 
    has_many :trips, through: :trip_memberships, uniq: true 
end 

class Trip < ActiveRecord::Base 
    has_many :trip_memberships, dependent: :destroy 
    has_many :members, through: :trip_memberships, source: :user, uniq: true 
end 

class TripMembership < ActiveRecord::Base 
    belongs_to :trip 
    belongs_to :user 
end 

當我添加一些用戶作爲釋放部件,像這樣的代碼:

trip = Trip.last 
john = User.last 
trip.members # => [] Empty right now 
trip.members << john 
trip.members # => [john] Contains John 
trip.members << john 
trip.members # => [john] Contains only John, but... 
TripMembership.all # => [TripMembership(trip, john), TripMembership(trip, john)] 
        # There is 2 memberships, even the accessor methods only show one 
        # member because of the :uniq option 

我不希望有在trip_memberships表重複,但我想跟着「告訴,不要問」的原則。我不想檢查給定記錄是否存在。

我加入這個驗證到TripMembership模型

class TripMembership < ActiveRecord::Base 
    belongs_to :trip 
    belongs_to :user 
    validates_presence_of :trip_id, :user_id 
    validates_uniqueness_of :trip_id, scope: [:user_id] 
    validates_uniqueness_of :user_id, scope: [:trip_id] 
end 

我預計<<concat方法,當我嘗試添加無法 保存的記錄,像有許多關係返回false ,但似乎與through關係它不會那樣工作。

trip.members << john # => ActiveRecord::RecordInvalid: Validation failed: Trip has already been taken, User has already been taken 

任何人都知道一個優雅的方式來實現這個?我認爲應該像這樣使用api。

if @trip.members << new_member 
    flash[:success] = "new member added" 
else 
    flash[:error] = "can't add this member to trip" 
end 
+0

我傾向於避免直接的數組操作 – apneadiving 2013-02-26 14:33:50

回答

1

我突然想到一個好主意。

因爲我剛剛發現鐵軌的標準行爲是,如果用戶不是一個新的記錄時拋出異常,我不能改變的一個衆所周知的方法的默認行爲,我會致以與名爲add_member的自定義方法關聯,該方法在開始/救援中僅別名呼叫<<

has_many :members, through: :trip_memberships, source: :user, uniq: true do 
    def add(*records) 
    self.<< records 
    rescue ActiveRecord::RecordInvalid 
    false 
    end 
end 

我有我自己的方法,按預期工作,無需更改導軌方法。

3

你可以嘗試這樣的:

if @trip.members.include?(new_member) 
    flash[:error] = "Member already exists" 
else 
    @trip.members << new_member 
    flash[:success] = "new member added" 
end 

編輯

has_many :members, through: :trip_memberships, source: :user do 
    def <<(member) 
    if self.include?(member) 
     false 
    else 
     super(Array(member)-self) 
    end 
    end 
end 
+0

當然我可以,但我的目標是添加記錄,而不要求包含。我剛剛有一個想法。 – 2013-02-26 14:41:14

+0

你不能沒有檢查。但是你可以通過覆蓋它來實現'''做你的工作。看我的編輯。 – codeit 2013-02-26 15:16:59

相關問題