2017-06-21 1 views
1

Je vais montrer un code lié, mais si vous avez besoin code complet, vous pouvez le trouver sur Github: https://github.com/maple-leaf/phoenix_todoPhoenix: afficher un modèle avec has_many garder un jet erreur préchargement

user_model:

defmodule PhoenixTodo.User do 
    use PhoenixTodo.Web, :model 

    @derive {Poison.Encoder, only: [:name, :email, :bio, :todos]} 

    schema "users" do 
    field :name, :string 
    field :age, :integer 
    field :email, :string 
    field :bio, :string 

    has_many :todos, PhoenixTodo.Todo 

    timestamps() 
    end 

    @doc """ 
    Builds a changeset based on the `struct` and `params`. 
    """ 
    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name]) 
    |> validate_required([]) 
    end 
end 

todo_model:

defmodule PhoenixTodo.Todo do 
    use PhoenixTodo.Web, :model 

    @derive {Poison.Encoder, only: [:title, :content]} 

    schema "todos" do 
    field :title, :string 
    field :content, :string 

    belongs_to :user, PhoenixTodo.User 

    timestamps() 
    end 

    @doc """ 
    Builds a changeset based on the `struct` and `params`. 
    """ 
    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, []) 
    |> validate_required([]) 
    end 
end 

user_controller:

defmodule PhoenixTodo.UserController do 
    use PhoenixTodo.Web, :controller 

    alias PhoenixTodo.User 

    def index(conn, _params) do 
     json(conn, User |> Repo.all() |> Repo.preload(:todos)) 
    end 

    def show(conn, %{"id" => id}) do 
     json(conn, User|> Repo.get(id) |> Repo.preload(:todos)) 
    end 

    def create(conn, data) do 
     user = User.changeset(%User{}, data) 
     #user = User.changeset(%User{}, %{name: "xxx", todos: [%PhoenixTodo.Todo{}]}) 
     json conn, user 
    end 
end 

Je peux obtenir tous les utilisateurs ou interroger l'utilisateur particulier de :index et :show, mais :create provoquera toujours une erreur sur association.

Demande avec: curl -H "Content-Type: application/json" -X POST -d '{"name": "abc"}' http://localhost:4000/api/users

Erreur soulevé comme ceci: cannot encode association :todos from PhoenixTodo.User to JSON because the association was not loaded. Please make sure you have preloaded the association or remove it from the data to be encoded

Comment précharger :todos quand :create? Et todos n'est pas un champ obligatoire lors de la création de l'utilisateur, pouvons-nous ignorer cette association?

+0

Avez-vous oublié de faire 'Repo.insert'? La création d'un ensemble de modifications n'introduira pas l'utilisateur dans la base de données. – Dogbert

+0

@Dogbert Je pense que ce n'est pas causé par 'Repo.insert'. Mais j'ajoute cela avant de renvoyer json, et la même erreur a été soulevée. Et le code de ': create' ressemble maintenant' user = User.changeset (% User {}, data) Repo.insert (utilisateur) json conn user' – tjfdfs

+0

Oui, comme vous l'avez compris, vous devez passer la structure utilisateur retournée par 'Repo.insert' à' json', pas le changeset. – Dogbert

Répondre

0

Enfin, je le fais fonctionner.

Il s'avère que json conn user est important. Il semble que json appellera Poison pour coder le Ecto.Changeset, pas un Ecto.Model, qui retournent par changeset. Nous devrions donc passer un Ecto.Model à JSON.

Et voici comment je le fais.

user = User.changeset(%User{}, data) 
IO.inspect user # Ecto.Changeset 
{:ok, u1} = Repo.insert(user) 
IO.inspect u1 # Model!! 
json conn, u1 |> Repo.preload(:todos) # now we can successfully preload :todos