I'm trying to get a basic database set up in Phoenix, and want a model similar to the Video model from the Phoenix Ecto tutorial--basically using has_many--along with uploading similar to the File Uploads tutorial.
In my case I'm wanting to allow users to upload multiple .csv's, which are added to the db. Right now I'm limiting one .csv upload on creating a user to focus on getting that much working. I'm also not concerned what I'll store--right now the path to where the .csv resides just to start out simple. In the future I might want to directly store the csv data.
I am getting the %Plug.Upload in the user_params, and am able to write that to a file, but I'm not sure how to add the path from that into the db.
Latest error is in users/model (see below).
Here's what I have so far:
models/csv.ex
defmodule Test.CSV do
use Test.Web, :model
schema "csvs" do
field :csv, {:array, :string}
belongs_to :user, Test.User
timestamps()
end
...
models/user.ex
defmodule Test.User do
use Test.Web, :model
schema "users" do
field :uname, :string
field :group, :string
has_many :csvs, Test.CSV
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:uname, :group])
# Wasn't sure what else to do here. Currently throws an error at this line with 'protocol Enumerable not implemented for %Plug.Upload{...filename...etc.}'.
# I figure I probably need to specify somewhere that I only want a certain field, like the path, but I'm not sure how to do that.
|> cast_assoc([:csvs])
|> validate_required([:uname, :group])
end
user_controller.ex
...
def create(conn, %{"user" => user_params}) do
changeset = User.changeset(%User{}, user_params)
case Repo.insert(changeset) do
{:ok, _user} ->
conn
|> put_flash(:info, "User created successfully.")
|> redirect(to: user_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
...
user/forms.html.eex
<%= form_for @changeset, @action, [multipart: true], fn f -> %>
...
<%= inputs_for f, :csvs, fn i -> %>
<div class="form-group">
<label>CSV</label>
<%= file_input i, :csv, class: "form-control" %>
</div>
<% end %>
...
<% end %>
I also made sure that I did ecto.migrate and added the csvs table to the db.
def change do
alter table(:users) do
# Hmm, not sure if that should have been a :map.
add :csvs, :map
end
end
Then there's whether I should be using a nested association (the right term?) or not, or going the route of embedded schema. Needless to say, I am new to Phoenix, and would greatly appreciate any thoughts on how to solve this. Thanks!
inputs_for f, :csvs, fn i ->- Joe Eifert