2016-09-15 4 views
2

наборы изменений у меня есть следующая модель (для чата), который у меня проблемы с при использовании: ревизииошибка чтения в Ecto

defmodule Elemental.TxChat.Room do 
    use Elemental.TxChat.Web, :model 

    schema "rooms" do 
    field :name, :string 

    # Foreign key indicating which user created this room 
    # One user can create any number of rooms 
    belongs_to :created_by, Elemental.TxChat.User 
    field :created_from_app, :integer 

    many_to_many :members, Elemental.TxChat.User, join_through: "rooms_users" 

    timestamps() 
    end 

    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name, :created_by, :created_from_app]) 
    |> validate_required([:name, :created_by, :created_from_app]) 
    end 
end 

Я тогда подумал, что я пытаюсь передать пустую-структуру к набору изменений и увидеть возникшую ошибку. Так что я сделал (после наложения):

iex(4)> c = Room.changeset(%Room{}, %{}) 
** (RuntimeError) casting assocs with cast/3 is not supported, use cast_assoc/3 instead 
     (ecto) lib/ecto/changeset.ex:440: Ecto.Changeset.type!/2 
     (ecto) lib/ecto/changeset.ex:415: Ecto.Changeset.process_param/8 
    (elixir) lib/enum.ex:1151: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3 
    (elixir) lib/enum.ex:1151: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3 
     (ecto) lib/ecto/changeset.ex:391: Ecto.Changeset.do_cast/7 
    (tx_chat) web/models/room.ex:19: Elemental.TxChat.Room.changeset/2 

Я тогда подумал, что модели, которые имели belongs_to и т.д., работали с cast_assoc, поэтому я изменил имя функции. И теперь:

iex(4)> c = Room.changeset(%Room{}, %{}) 
** (FunctionClauseError) no function clause matching in Ecto.Changeset.cast_assoc/3 
     (ecto) lib/ecto/changeset.ex:518: Ecto.Changeset.cast_assoc(%Elemental.TxChat.Room{__meta__: #Ecto.Schema.Metadata<:built, "rooms">, created_by: #Ecto.Association.NotLoaded<association :created_by is not loaded>, created_by_id: nil, created_from_app: nil, id: nil, inserted_at: nil, members: #Ecto.Association.NotLoaded<association :members is not loaded>, name: nil, updated_at: nil}, %{}, [:name, :created_by, :created_from_app]) 
    (tx_chat) web/models/room.ex:19: Elemental.TxChat.Room.changeset/2 

Что я делаю неправильно?

+2

ли вы просто изменить '' cast' к cast_assoc'? Попробуйте '|> cast (params, [: name,: created_from_app]) |> cast_assoc (: created_by)'. – Dogbert

+0

Сообщите мне, если это сработало, и я отправлю ответ с объяснением. – Dogbert

+0

@Dogbert Так вот какая тайна! Я действительно был настолько глуп, чтобы просто заменить 'cast' на' cast_assoc'. Большое вам спасибо за то, что помогли мне каждый раз. , , действительно ценю это. Пожалуйста, напишите ответ и объясните. – dotslash

ответ

4

Как поясняется в комментариях, вы хотите связать существующего пользователя с новой комнатой. Вы можете сделать это, добавив created_by_id в список полей, переданных cast, assoc_constraint(:created_by), а затем отправив идентификатор пользователя в ключе created_by_id по адресу Room.changeset/2. Это должно работать:

def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name, :created_by_id, :created_from_app]) 
    |> validate_required([:name, :created_by_id, :created_from_app]) 
    |> assoc_constraint(:created_by) 
end 

А затем создать номер:

Room.changeset(%Room{}, %{name: "foo", created_by_id: 1, created_from_app: 1}) 
|> Repo.insert 
Смежные вопросы