49341

How to import users from csv file with elixir/phoenix?

Question:

I have a csv file with a list of users and the following import method inside UserController and I would like to import these users by submitting the csv file with a form. And It looks like I'm doing it wrong.

<strong>users_controller</strong>

def import(conn, %{"user" => user_params}) do user_params["file"] |> File.stream!() |> CSV.decode |> Enum.each(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end) conn |> put_flash(:info, "Imported") |> redirect(to: user_path(conn, :index)) end

<strong>routes</strong>

post "/import", UsersController, :import, as: :import_csv

<strong>form</strong>

<%= render "import_form.html", changeset: @changeset, action: import_csv_path(@conn, :import) %>

-

<%= form_for @changeset, @action, [multipart: true], fn f -> %> <div class="form-group"> <%= label f, :file, class: "control-label" %> <%= file_input f, :file %> </div> <div class="form-group"> <%= submit "Submit", class: "btn btn-primary" %> </div> <% end %>

<strong>model</strong>

schema "users" do field :name, :string field :email, :string field :file, :any, virtual: true timestamps() end def changeset(struct, params \\ %{}) do struct |> cast(params, [:name, :email, :file]) |> validate_required([:name, :email]) |> unique_constraint(:email) end <hr />

<strong>The following code works from iex</strong>

def import(file) do file |> File.stream!() |> CSV.decode |> Enum.each(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end) end

Answer1:

You don't get a file back in your params. Here are the params I get back for a multipart file

[warn] module=UcxChat.AttachmentController line=10 function=create/2 attachment params: %{"channel_id" => "300233dd-782f-4718-9eed-00b8cc412a79", "description" => "", "file" => %Plug.Upload{content_type: "text/plain", filename: "test.txt", path: "/var/folders/wt/3q11kty15rqfb5v9rpqg0ssm0000gn/T//plug-1494/multipart-421483-239132-3"}, "file_name" => "test.txt", "type" => "text/plain", "user_id" => "427452eb-c9cf-457b-9c55-0904c9d24385"}

You can see that the params["file"] is a Plug.upload struct.

To get the actual file, you should get the :path field like:

def import(conn, %{"user" => user_params}) do user_params["file"].path |> File.stream!() |> CSV.decode |> Enum.each(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end) conn |> put_flash(:info, "Imported") |> redirect(to: user_path(conn, :index)) end

You probably also want to do some error handling. Something like:

def import(conn, %{"user" => user_params}) do user_params["file"].path |> File.stream!() |> CSV.decode |> Enum.map(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end) |> Enum.filter(fn {:error, cs} -> true _ -> false end) |> case do [] -> conn |> put_flash(:info, "Imported") |> redirect(to: user_path(conn, :index)) errors -> errors = parse_errors(errors) # create this fun conn |> put_flash(:erorr, errors) |> render("import.html") end end

Recommend

  • Rails ajax form not submitting from within another
  • I can't create model objects using accepts_nested_attributes_for. It won't create the nest
  • Rails has_many :through association: save instance into join table
  • PHP - sending email with attachment does not show message content
  • What is the likely cause of a net::ERR_CONNECTION_ABORTED when uploading a file to Spring
  • How to Add Polymorphic Comments to Feed?
  • Undefined navigator.push React-native 0.43.4
  • redirect_to root_url and return unless @user.activated
  • Laravel 4 routing not working due to .htaccess file?
  • Django Haystack Rebuild Index
  • Exception creating JSON with LINQ
  • Form tag not showing up in haml file
  • Use tryCatch within R loop
  • Exception gevent.hub.LoopExit: LoopExit('This operation would block forever',)
  • converter json to two dimensional array
  • cordova is not defined - cordova.js has already been loaded :: Ionic
  • Azure webjobs output logs indexing taking very long
  • Bootstrap (v3.3.4) glyphicons not displayed in IE when refresh page (F5)
  • Updating both a ConcurrentHashMap and an AtomicInteger safely
  • Python pickle not one-to-one: different pickles give same object
  • Implementing “partial void” in VB
  • Sending HTML Form Data to Spring REST Web Service
  • JqueryMobile Popup menu is not working
  • Django invalid literal for int() with base 10
  • Breaking out column by groups in Pandas
  • Not able to aggregate on nested fields in elasticsearch
  • How to handle images sent by a mobile device?
  • How do I alternate colors in Flat List (React Native)
  • $wpdb not working in file of WordPress plugin
  • Meteor helpers not available in Angular template
  • PHPUnit_Framework_TestCase class is not available. Fix… - Makegood , Eclipse
  • Modifying destination and filename of gulp-svg-sprite
  • what is the difference between the asp.net mvc application and asp.net web application
  • jquery mobile loadPage not working
  • Rearranging Cells in UITableView Bug & Saving Changes
  • How to get icons for entities from eclipse?
  • Proper way to use connect-multiparty with express.js?
  • Load html files in TinyMce
  • JaxB to read class hierarchy
  • Conditional In-Line CSS for IE and Others?