2016-08-07 9 views
0

私はRepoからフェッチされたモデルを持っており、いくつかの関連付けがあらかじめロードされています。私は、この大きな構造をGenServerで維持するために作成しますが、それを永続的に変更します。どうすればこれらの変更を維持できますか?たとえば、アソシエーションを使用してキャッシュモデルを変更する

query = from e in Empire, 
     where: e.user_id == ^user.id, 
     preload: [:board, {:board, [{:tiles, [:system]}]}] 
empire = Repo.one(query) 
#=> %Empire{ 
    id: 1, 
    currency: 1000, 
    board: %Board{ 
    empire_id: 1, 
    tiles: [ 
     %Tile{ 
     id: 1, 
     system: %System{ 
      id: 1, 
      tile_id: 1, 
      ore: 10 
     } 
     }, 
     %Tile{ 
     id: 2, 
     system: nil 
     } 
    ] 
    } 
} 

changed_empire = Empire.move_system(empire) 
#=> %Empire{ 
    id: 1, 
    currency: 500, #changed 
    board: %Board{ 
    empire_id: 1, 
    tiles: [ 
     %Tile{ 
     id: 1, 
     system: nil #changed 
     } 
     }, 
     %Tile{ 
     id: 2, 
     system: %System{ 
      id: 1, 
      tile_id: 2, #changed 
      ore: 5 #changed 
     } 
    ] 
    } 
} 

システムが1つのタイルから別のタイルに移動し、Empires通貨が変更されていることに注意してください。変更には、関連付けの追加または削除が含まれます。これはすべてクライアントからのデータなしで行われるため、サーバーがモデルを操作する方法の唯一の権限であるため、悪いデータが追加される心配はありません。

のparamsは構造体になりますので、私は通常の

changeset(model, params \\ %{}) do 
    model 
    |> cast(params, []) 
end 

に頼ることはできません。

update_change(struct) do 
    struct 
    |> change() 
    |> validate() 
end 

を示唆したが、今、私は手動で自分のupdate_change機能に送信する必要が関連する構造体の問題を持っているように私には、変更を使用して試すことができます。

これを実行するには、実行しているような余分な複雑さをすべて追加する必要はありませんか?

+0

あなたは 'Ecto.Changeset.change/2' https://hexdocs.pm/ecto/Ecto.Changeset.html#change/2私はまだ希望 – TheAnh

+0

を試すことができます検証を実行する。 change/2はそれらをスキップするようです。 –

+1

2番目のパラメータは構造体ではなく、paramsのマップにすることができます。構造体を持っていてそれを変換したい場合、Map.from_structはそのトリックを行うべきです。 –

答えて

0

コメントの助けを借りて私は私の質問を解決することができました。私は小さなヘルパーモジュールを作成して、すべてのデータを調べ、Map.from_structを呼び出します。これは普通のキャスト/ 3と組み合わせると、私が期待した結果が得られます。ここで

はヘルパーです:

defmodule RepoHelper do 
    def from_struct(struct) when is_map(struct) do 
    from(struct) 
    end 

    defp from(struct = %{__struct__: _}) do 
    Enum.reduce(Map.to_list(struct), struct, fn {key, val}, acc -> 
     Map.put(acc, key, from(val)) 
    end) 
    |> Map.from_struct() 
    end 

    defp from(map) when is_map(map) do 
    Enum.reduce Map.to_list(map), map, fn {key, val}, acc -> 
     Map.put(acc, key, from(val)) 
    end 
    end 

    defp from(list) when is_list(list) do 
    Enum.map list, fn item -> from(item) end 
    end 

    defp from(value), do: value 
end 
関連する問題