2016-04-12 4 views
0

エリクシルの新作で、エクトモデルの関係を変える方法を探しています。プリロードとエクトの関係を変更するには

schema "topic" do 
     has_many :topic_meta, PhoenixApp.TopicMeta 

と問合せ::

は、私が関係を持つモデルを持っていると仮定し

topic = from t in query, 
     left_join: meta in assoc(t, :topic_meta), 
     preload: [topic_meta: meta] 
     |> Repo.one 

は、リストフィールドでtopic_meta

をマップ%PhoenixApp.Topic{...}を取得し、私はtopic_metaフィールドのいずれかに変更値をしたいです:

changed_meta = %{List.first(topic.topic_meta) | last_read: "newValue"} 

質問:

私のクエリからtopicに提出された変更topic_meta関係を挿入する方法は?フィールドを更新するための新しいクエリを不要にします。

詳細でアップデート:

first_meta = List.first(topic.topic_meta) // this is first meta 

result = Repo.update!(PhoenixApp.Topic.changeset(first_meta, %{last_read: "newValue"})) 

case result do 
    {:ok, topic_meta}  -> 
// topic_meta successfully updated, but topic does not contain this model 
end 

答えて

1

あなたが更新する形であなたのchanged_metaを持っている場合は、Repo.update/2を使用する必要があります。

Repo.update(changed_meta) 

希望に役立ちます!

更新

あなたがそれをリロードすることなく、あなたのtopicで更新要素を見たい場合は、手動でtopic_metaの現在のリストを置き換えることができます。 changed_metaの1つを含む、

index = Enum.find_index(topic.topic_meta &(&1.id == changed_meta.id)) 
list = List.replace_at(topic.topic_meta, index, changed_meta) 
topic = %{topic | topic_meta: list} 
これにより

topic_metaのリストを更新しているでしょう最後の行からtopic

はあなたがchange_metaを用意している考えると、あなたのような何かを行うことができます。

+0

あなたの答えをありがとう。私は、「詳細を更新する」セクションの質問を詳述しました。問題は、 'Repo.update'の結果を元のデータとマージする方法でした。 – user1156168

+0

ああ!あなたが何を求めているのかが分かります。私は、不変性のためにそうすることの「簡単な」方法がないのではないかと心配しています。 'topic'はオブジェクト(Ruby/Javaなど)のようなものではないため、このような変更はすぐには反映されません。それを反映させる最も簡単な方法は、データベースからデータをリロードすることだけです。ここでは、Phoenixのアクションの分割が意味を成しています - あなたは 'update'アクションの値を更新し、ユーザーを' show'アクションの一種にリダイレクトします。ここで、更新されたデータはDBからきれいに取り出されます。 –

+0

ねえ、@ user1156168 - お願いします、更新された回答を見てください。コードは非常に冗長です(あなたがOO言語で同様のことをした場合に得られるものと比較して)。しかし、それはあなたが期待することを行うべきです。問題が少し明確になることを願っています! –

0

使用build_assochttps://hexdocs.pm/ecto/Ecto.html#build_assoc/3

changed_meta = Ecto.build_assoc(topic, :topic_meta, last_read: "newValue") 
Repo.insert!(comment) 
+0

新しい 'topic_meta'では大文字と小文字が区別されますが、associasionsが既にプリロードされている場合にはこれが行われます。 – user1156168