2016-05-13 79 views
1

我已閱讀this,所以我明白其中的差異。Rails 4 - has_one和belongs_to投擲錯誤

但我繼承了一個拋出奇怪行爲的應用程序(我想,也許我錯了,這是正常的)。

有2種型號:

class Pod < ActiveRecord::Base 
    has_one :pod_admin 
end 

class PodAdmin < ActiveRecord::Base 
    belongs_to :pod 
end 

在軌控制檯,我嘗試這樣做:

p = Pod.find(5) 

,它表明該吊艙具有pod_admin_id值的14。這是正確的。

我試圖改變PodAdmin:

p.pod_admin = PodAdmin.last 

,並拋出這個錯誤:

NoMethodError: undefined method pod_admin_id for #<PodAdmin:0x007fa401f1e710> 

這是爲什麼?我錯過了什麼?

編輯基於的意見/回答

,在不改變模型,我嘗試這樣做:

pa = PodAdmin.last 
pa.pod = p 

和這樣的作品,我看到控制檯返回最後PodAdmin用新pod_id。

pa.save 

p.save 

都拋出同樣的錯誤了。

如果我看一下數據庫模式,Pod表具有pod_admin_id字段,而PodAdmin表具有pod_id字段。

我繼承了這個模式,我只是想知道原始開發者是否正確設置了這個模式。當然,我應該能夠從任一方向更新關係 - 是不是創建has_one和belongs_to的關鍵,所以你可以有這樣的雙向關係?

EDIT 2

我發現這個問題,這是我已經添加了此行PodAdmin表,而不是吊艙表:

validates :pod_admin_id, uniqueness: {scope: :id, message: 'The Pod already has a PodAdmin'} 

道歉 - 但正如你所看到的,是什麼我想在這裏實現的目的是防止Pod有2個PodAdmins。這驗證似乎並沒有達到。

我可以這樣做:

p = Pod.find(5) 
pa_last = PodAdmin.last 
pa_first = PodAdmin.first 
pa_last = p 
pa_first = p 
pa_last.save 
pa_first.save 

現在無論PA的具有相同pod_id。 我該如何防止這種情況發生?

編輯3

大量的閱讀和測試後,並在兩地@Anand和@Spickerman的問題是,以前的開發人員把一個外鍵到這兩個表(在has_onebelongs_to)。只有belongs_to表應該有一個外鍵。此外,這種關係被定義爲錯誤的方式。但是,解決這個問題並不能保證可靠的解決方案。我強烈建議其他類似問題的人閱讀this

+2

你做錯了。隨着你的關聯設置,「pod_admins」表應該有'pod_id'。 – Pavan

+0

@Pavan是對的,你需要'pod_admins'表上的'pod_id',或'Pod'''屬於':pod_admin'而'PodAdmin'' has_one:pod' –

+0

pod_admins表有一個pod_id字段。我更新了我的問題來解釋 - 似乎我無法從任何一方更新關係。 – rmcsharry

回答

1

相反的p.pod_admin = PodAdmin.last,叫PodAdmin.last.pod = p - 正如其他人所提到的,pod_id在PodAdmin表,而不是其他方式。

更新:

基於更新問題,這個問題是因爲你有外鍵引用兩種方式 - 您應該已經pod_id在pod_admins表或豆莢表pod_admin_id,但不能同時使用。刪除其中一個與新的遷移,然後再次嘗試

> bundle exec rails g migration RemovePodIdFromPodAdmins 

# db/migrations/XXXX_remove_pod_admin_id_from_pods 
def change 
    remove_column :pods, :pod_admin_id 
end 

bundle exec rake db:migrate

然後,按照以上建議,請撥打

pa = PodAdmin.last 
pa.pod = p 
pa.save! 
+0

由於belongs_to在PodAdmin模型中,我不應該保留該外鍵,而是從has_one一側移除foreign_key(即從Pod表中刪除PodAdminID)? – rmcsharry

+0

我從Pods表中刪除了pod_admin_id。我仍然可以給2 PodAdmins相同的Pod。這是堅果。 – rmcsharry

+0

是的,@ rmcsharry - 我正在更新迴應以表明這一點。如果您從pod表中刪除pod_admin_id,它仍然允許兩個pod_admin擁有相同的pod,因爲'pod belongs_to pod_admin'表示每個實例可以屬於某個pod。但是,因爲你有'pod_admin has_one pod',pod.pod_admins將是未定義的,而pod.pod_admin將被定義(儘管它將返回的是未定義的)。 – Anand

1

外鍵始終屬於與belongs_to關聯的型號。

在您的例子PodAdminbelongs_toPod,因此您pod_admins表應該有一個pod_id列。

或者,你可以改變你的模型如下,以反映您的數據庫模式:

class Pod < ActiveRecord::Base 
    belongs_to :pod_admin 
end 

class PodAdmin < ActiveRecord::Base 
    has_one :pod 
end 
+0

pod_admins表確實有一個pod_id列。我用更多的信息更新了這個問題。 – rmcsharry

+0

外鍵只能存在於擁有belongs_to的模型的表中。另一個表格不能有這樣的列(並且也不需要該列)。要防止兩個PodAdmin擁有相同的Pod,請選擇我的第二個版本,並在belongs_to關聯時切換方向。 – spickermann

+0

謝謝,我試過了,從'has_one'表中刪除了列。我仍然可以將多個PodAdmin分配給Pod。我會嘗試你的第二個版本,但是很確定可以給每個PodAdmin分配多個Pod,因爲這不是1-n關係,所以不應該被允許。看來我必須在數據庫級執行此限制。 – rmcsharry