2017-03-17 75 views
1

我試圖在Phoenix中建立一個基本數據庫,並且想要一個類似於Phoenix Ecto tutorialVideo模型的模型 - 基本上使用has_many - 上傳類似於File Uploads tutorial將數據插入關聯(?)

在我的情況下,我想讓用戶上傳多個.csv,它們被添加到數據庫中。現在我限制一個.csv上傳創建用戶專注於獲得這麼多的工作。我也不關心我要存儲什麼 - 現在,.csv所在的路徑只是爲了開始簡單。將來我可能想要直接存儲csv數據。

我得到了user_params中的%Plug.Upload,並且能夠將它寫入到一個文件中,但我不確定如何將該路徑添加到數據庫中。

最新的錯誤是在用戶/模型(見下文)。

這是我到目前爲止有:

型號/ csv.ex

defmodule Test.CSV do 
    use Test.Web, :model 

    schema "csvs" do 
    field :csv, {:array, :string} 
    belongs_to :user, Test.User 

    timestamps() 
    end 
    ... 

型號/ 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 
... 

用戶/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 %> 

我也確保我做了ecto.migrate並將csvs表添加到db。

def change do 
    alter table(:users) do 
    # Hmm, not sure if that should have been a :map. 
    add :csvs, :map 
    end 
end 

然後是否應該使用嵌套關聯(正確的術語?)或不使用嵌入式架構的路由。不用說,我是鳳凰新手,對於如何解決這個問題的任何想法都非常感激。謝謝!

+0

在發生類似問題後,該帖子給了我適當的背景來幫助自己。 http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/ 我想你應該預先加載你的csvs。請說明您的表單開始的樣子。我認爲它應該是'input_for f,:csvs,fn i - >' – Johannes

+0

好吧,我一直在探討很多不同的文章,我不確定我應該怎麼做。我喜歡菲尼克斯的很多方面,但這部分似乎有太多潛在的解決方案,很難知道哪一個可以追求。如果有一種簡單的內置方式來處理我忽略的%Plug.Upload {}會很好。 @Johannes,我試着用inputs_for(將編輯我的帖子來反映這一點),但現在file_input表單不再顯示。不確定如何從那裏繼續......也許它在你鏈接的那篇文章中被覆蓋了。 – Aristoatle

回答

0

我真的很驚訝你怎麼搞清楚架構{:array, :string}使用這種符號...您的情況最簡單的解決辦法是讓UserCSV,這部分你有有效之間has_many關係。

現在就看你如何想存儲有關的數據庫 - 這些信息的CSV如果處理Plug.Upload沒什麼比文件多,但你需要定製外生將如何處理這種類型的與Ecto.Type,因爲文件是一個複雜的結構。

另一種選擇是解析CSV文件,然後把它放到CSV表,並使用User,propably這樣做的最好方法是使用CSV插件讀取文件的內容聯繫起來 - CSVLixir或任何其他 - 並將其與put_assoc結合使用。

就我個人而言,我不會存儲在數據庫中的整個文件,但引用它如。文件名和內容如果需要。