2016-05-13 9 views
1

私はthisを読みました。違いを理解しています。Rails 4 - has_oneとbelongs_to throwing errors

しかし、私は奇妙な動作を投げているアプリケーションを継承しています(私は間違っていると思いますが、これは正常です)。

2つのモデルがある:

p = Pod.find(5) 

と、このポッドは、これが正しい14のpod_admin_id値を有する示す:レールコンソールで

class Pod < ActiveRecord::Base 
    has_one :pod_admin 
end 

class PodAdmin < ActiveRecord::Base 
    belongs_to :pod 
end 

、私はこれを試みました。

私はPodAdminを変更しようとしました:

p.pod_admin = PodAdmin.last 

と、このエラーがスローされます。

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

それはなぜですか?私は何が欠けていますか?コメント/回答に基づいて

EDIT

は、モデルを変更せずに、私はこの試みた:

pa = PodAdmin.last 
pa.pod = p 

をし、それが動作しますが、私は、コンソールは新しいpod_idで最後PodAdminを返す参照してください。

しかし

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つのPodAdminを持つのを防ぐことです。これはそれを達成するようには見えません。

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を持っている:

私はこれを行うことができます。 どうしたら起こるのを防ぐことができますか?

EDIT 3

問題は、以前の開発者は両方のテーブル(has_onebelongs_to)への外部キーを置くということであった多くの読書と試験後と@Anandと@Spickerman両方のおかげで。 belongs_toテーブルのみが外部キーを持つ必要があります。また、関係は間違った方法で定義されていました。ただし、これを修正しても堅牢なソリューションは保証されません。私は非常に類似の問題を持つ他の人にthisと読むことをお勧めします。

+2

呼び出します。アソシエーション設定では、 'pod_admins'テーブルは' pod_id'を持っていなければなりません。 – Pavan

+0

@Pavanが正しいです。 'pod_admins'テーブルに' pod_id'が必要です。 '' Pod''は 'belongs_to:pod_admin'に' 'PodAdmin'' has_one:pod'を入れてください。 –

+0

pod_adminsテーブルにはpod_idフィールドがあります。私は説明するために私の質問を更新した - それはどちらの側からも関係を更新することはできないようだ。 – rmcsharry

答えて

1

代わりのp.pod_admin = PodAdmin.lastPodAdmin.last.pod = pを呼び出す - 他の人が言及したように、pod_idがPodAdminテーブルにある、およびありません他の方法で。

更新:

あなたが外部キー参照両方の方法があるので質問するアップデートに基づいて

は、問題がある - あなたはpod_adminsテーブルまたはポッドテーブルのpod_admin_idにpod_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モデルにあるので、私はその外部キーを保持して、foreign_keyをhas_one側から削除しないでください(つまり、PodテーブルからPodAdminIDを削除します)? – rmcsharry

+0

Podsテーブルからpod_admin_idを削除しました。私はまだ2つのPodAdminsに同じPodを与えることができます。これはナッツです。 – rmcsharry

+0

はい、@rmcsharry - 私はそれを示す応答を更新しています。pod_admin_idをpodsテーブルから削除すると、2つのpod_adminが同じpodを持つことができます。なぜなら、 'pod belongs_to pod_admin'は各インスタンスがいくつかのポッドに属することができるからです。しかし、あなたは 'pod_admin has_one pod'を持っているので、pod.pod_adminsは定義されませんが(pod_adminは返されますが、未定義です)、pod.pod_adminsは定義されません。 – Anand

1

外部キーは常にbelongs_toアソシエーションのモデルに属します。したがって、あなたのpod_admins表はpod_id列を持っている必要があり、あなたの例では

PodAdminbelongs_toPod、。

それともあなたは自分のデータベーススキーマを反映するために、以下にモデルを変更することができます、

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を持つモデルのテーブルにのみ存在しなければなりません。他のテーブルにはそのような列があってはなりません(その列は必要ありません)。同じPodを持つ2つのPodAdminを防ぐには、私の2番目のバージョンを選択して、belongs_to関連がある場合は方向を切り替えます。 – spickermann

+0

ありがとう、私は、 'has_one'テーブルから列を削除してみました。私はまだ複数のPodAdminをPodに割り当てることができます。私はあなたの2番目のバージョンを試してみますが、各PodAdminに複数のPodを割り当てることが可能であることは間違いありませんが、これは1-nの関係ではないので許されるべきではありません。私はこの制限をデータベースレベルで強制しなければならないようです。 – rmcsharry

関連する問題