2016-03-18 15 views
9

私はこのようなサブスクリプションを持っています。Ectoで関係を更新するにはどうすればよいですか?

:私は、サブスクリプション

にユーザーを関連付ける

defmodule Rebirth.Subscription do 
    use Rebirth.Web, :model 

    schema "subscriptions" do 
    ... 
    belongs_to :user, Rebirth.User 
    ... 
    end 

    ... 

    def update_user(model, params \\ :empty) do 
    model 
    |> cast(params, @required_fields, @optional_fields) 
    |> cast_assoc(:user, required: false)  
    end 
end 

は、だから、私はそれを実行すると、私は次のエラーを取得する

Rebirth.Subscription.update_user(subscription, %{user_id: 1}) 

または

Rebirth.Subscription.update_user(subscription, %{user: user}) 

を試してみました

** (ArgumentError) unknown assoc `user` in `cast_assoc` 

user_idを更新するにはどうすればよいですか?

ありがとうございます!

+0

現在、同じ問題が発生しています。:/ –

+0

私はまだそれを修正する方法を見つけていませんでしたが、掘り下げて、私は 'Ecto.Changeset.cast_relation/4'に問題を切り分けました。具体的には、 'Map.get(types、key)'です。この関連付けは、モデル「タイプ」の1つではありません。 –

+0

まあ、私は "それは夜の真ん中で、私はこれに疲れました"解決策は、 'cast_assoc'を削除し、' user_id'を必要なパラメタのリストに追加することです。まともな一時的な回避策です。 –

答えて

11

cast_assocは、「関連するモデルをキャスト」するために使用され、has_onehas_manyで使用することができます。 belongs_to relationは、呼び出されるモデル内の外部IDを定義します。 has_manyおよびhas_oneは、外部キーを持つ「other」オブジェクトに依存しています。

他の多くのオブジェクトを持つオブジェクトを作成する場合は、それらが有効であるかどうかをすべてチェックすることが理にかなっています。 cast_assocはそれぞれのモジュールでcastを呼び出します。

ユーザーは多数のサブスクリプションを持つことができます(おそらく、私はここで推測しています)。サブスクリプションを作成するときにユーザーを作成し、ユーザーがcast_assocで有効かどうかを確認するのは意味がありません。通常、この場合、ユーザーはすでにデータベースに存在します。あなたのケースでは

にはあなたしか関連付けられているモデルがキャストに存在するかどうかを確認したいので、あなたが使用する必要があります。

|> assoc_constraint(:user) 

user_idがデータベースに存在する与えられた場合、これは、ユーザーを検証するが、チェックしません。ユーザーのサブスクリプションを更新したい場合さて、あなたはこれを行うことができます。

user = Repo.get(User, id) 
subscription = Ecto.build_assoc(user, :subscriptions, other_fields_as_map) 

注意がそれはユーザモデルのhas_onehas_manyが必要です。

それとも、前にしようとしたとして、あなたは、単にユーザIDを更新することができます。

Rebirth.Subscription.update_user(subscription, %{user_id: 1}) 

、与えられたユーザIDが存在する場合、この時間は、それがデータベースをチェックしますが、あなたは全体のユーザーオブジェクトを渡すことはできませんここに。

関連するユーザーを更新する場合は、2つの手順で明示的に行う必要があります。 a)ユーザを取得する、b)モジュールで定義されたチェンジセットを使用してユーザを更新する。

最後に、ユーザーを更新するための個別の検証を行わない場合(このシナリオではそうは思わない)、関数の名前をupdate_userからchangesetに変更するとよいでしょう。同じチェンジセットをモデルの作成と更新に使用できます。

+0

ありがとう!つまり、ユーザーのサブスクリプションではなくサブスクリプションでユーザーを設定する唯一の方法は、user_idを設定することですか?私が間違っていない場合、これは新しいサブスクリプションを作成します:Ecto.build_assoc(user、:subscriptions、other_fields_as_map)? –

+0

それは正しいです。ユーザーが多数のサブスクリプションを持つことができるユーザーであるため、サブスクリプションにユーザーを設定することは意味がありません。そして、そうです、 'build_assoc'は、' user_id'が設定された新しいサブスクリプションを作成します。これは、IDを取得して、手動でアソシエーションを認識してサブスクリプションに設定するだけの簡略化されたものです。 – tkowal

関連する問題