« Back to channel list

#elixir-lang - 13 May 2019

« Back 1 day Forward 1 day »
[00:00:33] atk: has joined #elixir-lang
[00:27:22] orbyt_: has joined #elixir-lang
[00:30:42] blahdodo: has joined #elixir-lang
[00:46:17] Exuma: has joined #elixir-lang
[01:07:19] carldd: has joined #elixir-lang
[01:18:26] jgpawletko: has joined #elixir-lang
[01:49:14] tomterl: has joined #elixir-lang
[01:49:34] thomasross: has joined #elixir-lang
[01:56:49] thomasross: has joined #elixir-lang
[02:09:46] infowolfe: has joined #elixir-lang
[03:13:11] harfangk: has joined #elixir-lang
[03:22:24] carldd: has joined #elixir-lang
[03:28:39] griffinbyatt: has joined #elixir-lang
[03:40:46] Notimik: has joined #elixir-lang
[03:46:47] Saukk: has joined #elixir-lang
[03:59:37] notzmv: has joined #elixir-lang
[04:15:07] Guest42: has joined #elixir-lang
[04:43:20] voltone: has joined #elixir-lang
[04:44:22] ur5us: has joined #elixir-lang
[05:05:48] craigp_: has joined #elixir-lang
[05:30:38] voltone: has joined #elixir-lang
[05:47:59] serafeim: has joined #elixir-lang
[06:03:38] proteusguy: has joined #elixir-lang
[06:05:32] orbyt_: has joined #elixir-lang
[06:30:56] nickjj_: has joined #elixir-lang
[06:32:32] kyrylo: has joined #elixir-lang
[06:35:24] mbuf: has joined #elixir-lang
[06:45:22] serafeim: hello, i've got a UTC date in my database. how can I display it in local time in an eex template ?
[06:50:10] netrino: has joined #elixir-lang
[06:51:24] PragTob: has joined #elixir-lang
[06:51:29] Nicd-: 1) ask for your user's local timezone, 2) use timex or lau/calendar to convert datetime to local time, 3) format time
[06:51:42] Nicd-: or use JS to convert it on client side
[06:52:16] serafeim: let's say that I know which is the user's timezone (Europe/Athens). then ? do i need to install a dependency ?
[06:52:23] serafeim: i don't want to mess with js
[06:55:11] Nicd-: then step 2
[07:00:13] mozzarel1: has joined #elixir-lang
[07:00:51] jegaxd26: has joined #elixir-lang
[07:04:47] DeadTrickster: has joined #elixir-lang
[07:10:21] orbyt_: has joined #elixir-lang
[07:11:43] orbyt_: has joined #elixir-lang
[07:12:34] serafeim: Nicd- so 'ill need to install timex ?
[07:13:58] Nicd-: apparently you can do it with Elixir if you have 1.8+ and you have a timezone database installed (like https://hex.pm/packages/tzdata)
[07:14:14] Nicd-: then you can use DateTime.shift_zone
[07:14:42] serafeim: all right thanks
[07:15:48] serafeim: also is there a proper way to set some configuration settings for me phoenix project ? (i.e default timezone = zzz) and then how can I access them >?
[07:16:15] serafeim: is something like config :appname, config_param1: "Z", config_param2: "ZZ" ok ?
[07:17:42] Nicd-: I don't think there is a default timezone setting
[07:35:33] serafeim: no, i mean set it myself as an option
[07:35:48] serafeim: so i'll be able to reuse it in multiple places
[07:36:05] Nicd-: yeah, you can set stuff in config that way
[07:36:18] Nicd-: and use `Application.get_env(:appname, :param)` to get them
[07:37:12] Nicd-: note that you need to use special care when working with releases (namely to use the distillery config providers to customise config after compiling the release)
[07:48:54] Sgeo: has joined #elixir-lang
[07:58:19] jegaxd26: has joined #elixir-lang
[07:58:48] inhortte: has joined #elixir-lang
[08:20:08] snapet: has joined #elixir-lang
[08:44:10] jegaxd26: has joined #elixir-lang
[08:51:53] snapet: has joined #elixir-lang
[08:58:42] wonko7: has joined #elixir-lang
[09:03:04] ur5us: has joined #elixir-lang
[09:06:10] lexmag: has joined #elixir-lang
[09:07:31] craigp_: has joined #elixir-lang
[09:31:46] serafeim: Nicd- i've decided to not work with distillery for now (because of problems as the one you've mentioned)
[09:32:58] serafeim: however i'd really like to know: what would be the problem with this configuration ( config :appname, config_param1: "Z", config_param2: "ZZ") if i used distillery
[09:46:32] Nicd-: the problem most run into is that the config settings are normally set at compile time
[09:47:01] Nicd-: so when you create the release, the config is builtin. then you wonder how to change the config when you already have a created release. that's what the distillery config providers are for
[09:48:31] serafeim: Nicd- you mean if I need to change the config_param1 to a different value I'll need to re-deploy the whole application ?
[09:48:37] serafeim: that's what I actually had in mind :)
[09:49:26] serafeim: django settings also work more or less like this so it's not something new to me
[09:51:20] Nicd-: yes you have to rebuild the release unless you are using config providers or environment variables
[09:52:28] serafeim: if i want to have settings that are easy to configure i'll probably save them to redis or something similar
[09:53:09] serafeim: or even to the database
[09:53:09] Nicd-: it's a decision to make. for example I don't want to have to rebuild my blog engine to change the blog posts data path or the number of posts on the page or the analytics code (those come from config)
[09:53:33] Nicd-: so I have a custom-config.exs that distillery uses to apply configs on top of the built configs when the release starts
[09:54:06] serafeim: yes i understand what you mean
[09:54:53] Nicd-: that would also allow me to build one release that I could distribute to people that want to use my blog engine and they could customise their installation with the config file
[09:57:20] serafeim: another thing i wanted to ask is that I've seen that when a user logs out it is proposed to do conn |> configure_session(drop: true) to reset the session. however, when this is used I can't use flash messages because they are lost
[09:58:01] Nicd-: yes they are stored in the session
[09:58:03] serafeim: so i read somewhere (actually here https://stackoverflow.com/questions/42910224/put-flash-not-works-with-configure-sessiondrop-true) that you can use clear_session for the same (more or less) purpose... is this ok or are there security implications i'm not aware of ?
[09:58:40] Nicd-: it's ok since it clears all keys from the session, effectively emptying it
[10:01:11] serafeim: excellent thank you
[10:01:24] serafeim: because i'm not sure about all security considerations of phoenix :|
[10:10:10] jegaxd26: has joined #elixir-lang
[10:16:36] serafeim: theres a "custom mix tasks" thing (i.e https://elixirschool.com/en/lessons/basics/mix-tasks/)... why do i need to actually add a custom mix task instead of just adding an exs script that I run with mix run ? like priv/repo/seeds.exs
[10:30:23] voltone: has joined #elixir-lang
[10:37:29] zigpaw: has joined #elixir-lang
[10:40:30] serafeim: maybe i could ask why priv/repor/seeds.exs is a script and not a custom mix task ?
[10:48:52] ericmj: because you wouldn't able to call it when mix is not available
[10:48:59] ericmj: for example when seeding your staging environment
[10:53:52] gvaughn: has joined #elixir-lang
[10:56:16] ur5us: has joined #elixir-lang
[11:02:09] serafeim: ericmj that's interesting
[11:02:32] serafeim: ericmj however so why should anybody write custom mix tasks instead of just writing exs scripts ?
[11:02:52] ericmj: it can be useful to have access to the mix context
[11:03:02] ericmj: for example your configuration in mix.exs
[11:03:03] Nicd-: I use them for development time tasks
[11:03:29] serafeim: Nicd- like ?
[11:04:05] Nicd-: like frontend building stuff, or downloading latest geoip database, or stuff like that
[11:12:23] serafeim: i can't find a real advantage though in favor of using custom mix tasks.
[11:12:38] serafeim: all of these can also be done with plain scripts
[11:31:55] kyrylo: has joined #elixir-lang
[11:39:28] voltone: has joined #elixir-lang
[11:40:24] davic: A question will .deb files be created with the new Distillery replacement?
[11:40:34] davic: or is that something that will be done by the coder?
[11:40:52] davic: Currently I run https://hex.pm/packages/distillery_packager
[11:49:53] snapet: has joined #elixir-lang
[11:54:04] targaf: has joined #elixir-lang
[12:02:15] gvaughn: has joined #elixir-lang
[12:03:19] jegaxd26: has joined #elixir-lang
[12:12:29] either|or: has joined #elixir-lang
[12:30:48] proteusguy: has joined #elixir-lang
[12:50:30] benjamins: has joined #elixir-lang
[12:53:00] wonko7: has joined #elixir-lang
[12:57:38] helpa: has joined #elixir-lang
[12:58:47] RJ2: has joined #elixir-lang
[12:59:13] jhill_: has joined #elixir-lang
[12:59:13] dch_: has joined #elixir-lang
[12:59:56] samrose: has joined #elixir-lang
[13:00:00] nageV: has joined #elixir-lang
[13:00:27] jkva: has joined #elixir-lang
[13:00:45] alex88: has joined #elixir-lang
[13:02:12] asonge: has joined #elixir-lang
[13:02:31] dnyy: has joined #elixir-lang
[13:02:40] uranoss: has joined #elixir-lang
[13:02:50] burbas: has joined #elixir-lang
[13:02:58] pmbauer: has joined #elixir-lang
[13:03:52] DukeDave: has joined #elixir-lang
[13:10:37] gvaughn: has joined #elixir-lang
[13:13:23] benjamins: has joined #elixir-lang
[13:13:56] profit_: has joined #elixir-lang
[13:14:16] OvermindDL1: has joined #elixir-lang
[13:15:34] zkat: has joined #elixir-lang
[13:19:29] jegaxd26: has joined #elixir-lang
[13:22:51] duoi: has joined #elixir-lang
[13:27:51] mcspud: has joined #elixir-lang
[13:33:36] lauromoura: has joined #elixir-lang
[13:44:58] gvaughn: has joined #elixir-lang
[13:45:25] duaneb: has joined #elixir-lang
[13:45:32] fmccann: has joined #elixir-lang
[13:53:17] hypercore: has joined #elixir-lang
[13:54:42] hypercore: what do forms when regarding referenced schemas? e.g. say my Page belongs to an Author, can i put <%= text_input f, :author %> and <%= text_input f, :author_id %>?
[13:55:05] hypercore: how does ecto intepret these forms and is there a priority?
[13:57:13] fastfresh: has joined #elixir-lang
[13:58:17] lexmag: has joined #elixir-lang
[13:59:54] ankhers: hypercore: I assumed the Page belongs_to an Author (belongs_to :author, MyApp.Author). If that is the case, I believe what you wrote would error because the Page actually has an :author_id field, not an :author field. You will probably want to have a dropdown to select the Author of the Page. Or, if the author is the person creating/editing the page, you can just do it on the server side so that you can ensure no one puts the wrong
[13:59:54] ankhers: information in.
[14:01:20] either|or: has joined #elixir-lang
[14:01:29] jeffweiss: has joined #elixir-lang
[14:03:27] hypercore: Ankhers: hmm strange, doesn't seem to save on create_page
[14:04:05] hypercore: but it's listed in my params as "author_id"
[14:05:25] hypercore: and it's definitely casted in my changeset
[14:05:47] hypercore: Ankhers: all good
[14:06:08] bakedb_: has joined #elixir-lang
[14:06:09] hypercore: just hadn't implemented the case for if an author exists to show up in the form :P
[14:06:45] ankhers: No problem!
[14:09:28] lexmag: has joined #elixir-lang
[14:13:47] Gazler: josevalim: Just realised a neat feature of Mox, it is called in the process of the calling context, so you can easily trigger handle_info from within the expectation.
[14:14:20] josevalim: gazler: wait what?! :D
[14:14:49] tnez: has joined #elixir-lang
[14:14:50] Gazler: Haha, I'm sure it was intentional, I've just never had to use it before.
[14:15:28] lexmag: has joined #elixir-lang
[14:16:27] nickjj: when testing functions that use Task.start is there a better way to ensure they finish before killing the process rather than adding sleep calls into the test? i fixed it by sleeping for 1 second but 1 second is forever when 40 tests finish in 750ms, it's over doubling my entire test suite's duration
[14:18:11] benwilson512: nickjj: monitor the pid and wait till you receive a DOWN message
[14:19:21] nickjj: benwilson512, from the docs i think task.start mentioned it's for "set it and forget it" type of things, is it even possible to monitor that type of task?
[14:19:38] benwilson512: you can always explicitly monitor the returned pid. regardless
[14:20:06] benwilson512: 1) I'm not generally a fan of un supervised processes, they'll hang around even if you restart your application (within the same vm)
[14:20:13] benwilson512: (restarting the VM always kills everything of course)
[14:20:31] nickjj: my app is running in docker, so in theory the VM would be getting shut down on app restart
[14:20:39] either|or: has joined #elixir-lang
[14:20:50] benwilson512: not necessarily, your app can be restarted within that VM if your top level supervisor crashes
[14:21:02] nickjj: but maybe i'm going about this wrong in the first place, maybe i should explain what i'm using it for?
[14:21:06] benwilson512: 2) you may want to wrap your Task.start calls in some kind of function that does `if Application.get_env(:my_app, :run_tasks), do: Task.start(fun)`
[14:21:07] lexmag: has joined #elixir-lang
[14:21:12] benwilson512: and then you set that false in tests
[14:22:33] nickjj: the use case is on deleting a user profile image, i have a function that does: 1. deletes the filename reference in that user's record, 2. uses Task.start to File.rm_rf the file from disk
[14:22:35] Gazler: I use the 2nd pattern sometimes, for things that are convenient to be synchronous in tests, such as sending emails.
[14:23:23] Gazler: You can use a Task.Supervisor to ensure the process is supervised.
[14:23:26] nickjj: right now it's not in a transaction because i'm not sure how to do that, but maybe the rm_rf isn't really necessary to put into a task?
[14:23:41] benwilson512: nickjj: transactions wouldn't apply to file operations anyway
[14:23:44] nickjj: a local rm -rf should finish in milliseconds
[14:24:17] benwilson512: nickjj: making it synchronous seems like a reasonably good idea
[14:24:37] nickjj: gazler, if you go down that path, would you put every database call in task.start? because it "should" always complete in milliseconds as well
[14:25:32] nickjj: sometimes you need to block i guess, if a query takes 400ms to complete
[14:25:33] Gazler: nickjj: Depends what I am doing. If I need the data, then I'll do it synchronously.
[14:26:05] benwilson512: nickjj: it's about guarantees
[14:26:12] Gazler: If it is something I want to run in the background, I'll use Task.Supervisor.async_nolink/3
[14:26:16] benwilson512: the nice thing about making it sync, is that if the action completes, everything happened
[14:26:46] nickjj: benwilson512, yeah i think looking back putting it into a task.start might not even make sense given how it's being used
[14:27:03] jeffro_: has joined #elixir-lang
[14:27:20] nickjj: user POSTs that they want to delete the image -> their db record gets adjusted -> the file gets removed from disk -> a response is returned which should show them their profile image is gone
[14:27:52] nickjj: from their POV i guess the file delete isn't important because the db record is what dictates showing it or not
[14:28:25] nickjj: that is what made me put it into a task.start in the first place
[14:29:13] Gazler: It might matter more if you change from a local file store in future.
[14:29:37] nickjj: gazler, yeah at some point it may end up being in an S3 bucket
[14:30:19] benwilson512: the thing I don't like about Task.start is you have no guarantees
[14:30:23] benwilson512: suppose you're on S3, and it's down
[14:30:29] benwilson512: the file isn't deleted, and the file is never deleted
[14:30:38] benwilson512: and you don't even really know if it is or not
[14:30:47] nickjj: yeah, in a perfect world i would want it to try deleting the file at least 5-10 times with some type of exponential back off
[14:30:57] Gazler: Yeah, we flag for deletion and do a transactional delete later.
[14:31:29] nickjj: because that behavior doesn't seem to easy to implement, at least not for a newbie like myself, task.start's complexity level is like a 2, but that perfect world solution is a 9.9 out of 10 in my mind
[14:32:18] benwilson512: sure, but in the simple world you're in, doing it sync is also fine
[14:32:22] benwilson512: and is easier to work with in this case
[14:32:42] benwilson512: even if it's on s3 you're only adding a couple hundred ms to the response time, which is reasonably acceptable in a "delete the image" scenario
[14:33:07] Kerem: has joined #elixir-lang
[14:34:22] nickjj: maybe, but that also seems not easy if it ends up being on s3, because you'd probably need to handle errors in the case it doesn't deleted, but the outcome would be hidden from the user which makes it seem strange in the end
[14:35:18] nickjj: a user should still be able to disassociate their profile image if s3 happens to be down
[14:35:32] hypercore: guys should there be an "id" field in a schema form?
[14:35:46] Gazler: nickjj: You need to look at the impact of the file remaining then. From a user data perspective.
[14:36:13] benwilson512: nickjj: your sync and your Task.start both suffer from that problem
[14:36:29] benwilson512: nickjj: if you want that to be the case you need to move managing the files to a completely separate thing
[14:36:47] benwilson512: some kind of process in your supervision tree that looks for files flagged for deletion periodically
[14:36:53] nickjj: gazler, yeah that's a good idea, a happy medium might be to keep it as Task.start -- but if it gets to the point where the data perspective is beyond "who cares", then write a simple recurring task which runs once a day or week to delete unassociated profiles from disk?
[14:36:56] benwilson512: or use quantum and schedule it like cron
[14:37:25] Gazler: benwilson512: Don't forget you'll need some sort of persistent storage.
[14:37:40] benwilson512: gazler: he already has some sort of DB
[14:38:03] Gazler: Yeah, you'll need to mark it in there.
[14:38:22] Gazler: Or you can query S3 and do a diff, that gets pretty expensive though.
[14:38:28] nickjj: it's a db with an arc record that stores the filename + updated time in a map
[14:38:41] nickjj: the arc defaults basically
[14:39:07] Gazler: You can either flag it as deleted (soft delete) or persist it somewhere else, in a new table.
[14:41:43] Kerem_: has joined #elixir-lang
[14:41:47] nickjj: yep, or maybe even get away with just checking for nil user photos in the db i think
[14:42:10] nickjj: if photo field is nil && user has photo image on disk then delete image on disk
[14:42:29] Kerem: Hi, got a problem with phoenix framework and plugs, when i try an halt a conn within a module plug it cannot find halt; http://oneclickpaste.com/5167/
[14:44:26] chrismccord: Kerem you need parens
[14:44:31] chrismccord: json(conn, %{status: 401, message: "Unauthorized"} |> halt)
[14:44:39] chrismccord: that's how your code is treated currently ^
[14:45:30] Kerem: Did the trick! Thx :D
[14:47:02] nickjj: Kerem, if you run that through mix format does it warn you about that?
[14:48:12] Kerem: is it just mix format?
[14:49:08] Kerem: hmm yea it reformated to chirsmccords example
[14:49:56] Kerem: didnt know about mix format! :D cool
[14:49:57] lexmag: has joined #elixir-lang
[14:50:59] Nicd-: you can have your editor autoformat files using it
[14:51:09] hypercore: how do i case match on get_page!(page_id)?
[14:51:09] nickjj: it's like being able to summon chrismccord on your command line, plus it works offline
[14:51:46] Nicd-: hypercore: like normal?
[14:52:07] hypercore: Nicd-: {:ok, page} -> {:error, error}?
[14:52:31] hypercore: or try catch
[14:52:54] Nicd-: well usually you use a non-! version if you want to match it in a case
[14:53:15] hypercore: Nicd-: does phx.gen generate that function?
[14:53:30] Nicd-: I don't know, I don't use phx.gen
[14:54:02] serafeim: has joined #elixir-lang
[14:54:19] Nicd-: if it does, it's in some file so go look for it
[14:55:55] Exuma: has joined #elixir-lang
[14:57:40] gvaughn: has joined #elixir-lang
[14:58:29] hypercore: Nicd-: it's not, have to create it
[14:58:31] gvaughn_: has joined #elixir-lang
[15:00:48] benwilson512: unrelated: I'm writing phoenix html for the first time in a very long time
[15:01:00] benwilson512: so far so good, although vscode auto completion is decidedly worse inside .eex files
[15:01:16] benwilson512: am I doing something wrong there, or is that just how it is?
[15:02:14] Kerem: Any good way of findin list intersection?
[15:02:40] benwilson512: Kerem: MapSet.intersection(MapSet.new(list1), MapSet.new(list2))
[15:03:32] Kerem: found that to, was hoping for a simple function for it :/
[15:03:50] benwilson512: how is that not simple?
[15:04:07] Nicd-: you can write a function for it :)
[15:04:12] hypercore: why does redirect(socket, to: Routes.page_path(socket, :index)) not redirect me?
[15:04:26] benwilson512: you can do the O(n^2) way if you want: for x <- list1, x in list2, do: x
[15:04:44] Nicd-: hypercore: what did it do instead?
[15:05:24] Nicd-: also do you need to use live_path?
[15:05:45] hypercore: Nicd-: it returns the matching case, i.e. {:error, message}
[15:05:57] hypercore: Nicd-: not 100% sure, but i don't think so
[15:05:58] Nicd-: the redirect?
[15:06:04] Nicd-: then your code is wrong
[15:06:12] hypercore: Nicd-: can i put a redirect in a case statement?
[15:06:27] Nicd-: cannot help you further without full code
[15:06:28] hypercore: what about an var = case .. do?
[15:06:34] hypercore: ok let me post it
[15:06:37] Nicd-: of course
[15:07:00] Kerem: i am loving automatic code formatting using mix format! :D
[15:07:55] hypercore: Nicd-: https://paste.ubuntu.com/p/YwFyTd8Cps/
[15:08:35] Nicd-: that is not the full code
[15:08:39] Nicd-: not even the full function
[15:09:34] hypercore: that's the case statement, isn't that sufficient?
[15:10:47] hypercore: all that's before it is the controller action: def mount(%{path_params: %{"id" => id}}, socket) do\n id = 10\n ...
[15:11:19] hypercore: sorry, user = %{id: 10}
[15:11:23] hypercore: (which is just filler)
[15:11:50] Nicd-: it is not sufficient because I don't know what you do with page after the code. anyway that redirect call won't return {:error, message}
[15:14:31] hypercore: inspecting page gives me %Phoenix.LiveView.Socket{...}
[15:14:50] hypercore: with the redirect path correctly set
[15:16:18] hypercore: maybe it's a live view thing, this normally works in a non-LV controller
[15:16:42] Nicd-: so it depends on what you do with page after that code
[15:17:05] Nicd-: and that we cannot know telepathically
[15:17:34] hypercore: Nicd-: i thought redirect stops the flow of a controller and... redirects
[15:17:43] Nicd-: it does not
[15:17:46] Nicd-: it returns a value
[15:18:05] hypercore: ok that's the problem, didn't know that
[15:18:16] hypercore: thanks for clearing that up :P
[15:23:36] hypercore: Nicd-: what would you suggest i pass to def mount() if the author isn't verified to view the page?
[15:23:55] Nicd-: I have no idea what is mount
[15:26:08] hypercore: https://github.com/phoenixframework/phoenix_live_view/blob/master/lib/phoenix_live_view.ex#L271
[15:26:52] hypercore: maybe this is a better link -> https://github.com/phoenixframework/phoenix_live_view/blob/master/lib/phoenix_live_view.ex#L123
[15:28:06] Nicd-: I haven't used livevie
[15:28:24] Nicd-: but presumably you render something that tells the user they are not allowed to do that
[15:28:56] hypercore: Nicd-: didn't think about that as a solution... thanks!
[15:31:23] aalmazan: has joined #elixir-lang
[15:39:06] griffinbyatt: has joined #elixir-lang
[15:44:20] nickjj: Nicd-, on the topic of not returning early, how do you deal with controllers where you often want to render different things based on certain conditions?
[15:44:40] Nicd-: conditions such as?
[15:45:01] Nicd-: I find usually `with` is suitable to deal with a happy path and one or several failures
[15:45:10] nickjj: i have a controller action that responds 3 different ways and i feel like the code is starting to get a little hard to read / reason about but i'm not sure how to improve it
[15:45:35] nickjj: here's the exact code: https://gist.github.com/nickjj/db8a47eb14545649eaa64989682b96d0
[15:46:40] Nicd-: lemme rework that a bit
[15:49:40] wsieroci: has joined #elixir-lang
[15:51:07] laut: has joined #elixir-lang
[15:51:21] nickjj: i think refactoring the deactivated_at == nil into a virtual attribute as "active?" is something i'll eventually do to make the code more readable at a glance but that doesn't change the controller flow
[15:52:12] Gazler: nickjj: You can pattern match that part. case Accounts.get_by_email(email) do {:ok, %{deactivated_at: nil} = user} ... {:ok, user} ...
[15:52:45] Nicd-: good point
[15:53:06] Nicd-: I wrote using `with` without that realisation: https://gist.github.com/Nicd/93bb55af301af4c2edce84481b1b9ce9
[15:54:35] Gazler: https://gist.github.com/Gazler/a621c7af8da7a61786963c946086d154
[15:54:41] nickjj: what would the pattern match approach look like in a gist? too many ... for me to reason about that currently heh
[15:55:33] Gazler: I'd move lines 4 and 5 out into a single function.
[15:56:06] Gazler: Accounts.refresh_email_token_and_notify!(user)
[15:56:11] nickjj: that is quite a bit more readable
[15:56:38] nickjj: would you also change {:ok, %{deactivated_at: nil}} to {:ok, user.active?} , and set up a virtual attr for that?
[15:56:54] nickjj: actually i have no idea what the real syntax would look like for that
[15:57:10] Gazler: It'd be {:ok, %{active?: false} = user}
[15:57:16] nickjj: because, :ok, true wouldn't make sense since i would still need the user
[15:58:13] nickjj: is 4/5 being put into a single action mainly to avoid having to reassign user?
[15:58:33] Gazler: Just easier to reason about what is going on in my opinion.
[15:59:11] Gazler: You should probably reassign if you need to. user = Accounts.refresh_email_token_and_notify!(user)
[15:59:55] Gazler: I'd at least move line 5, sending emails usually isn't a controller concern.
[16:00:17] nickjj: that returns back the user with a token added to a specific db field, and this token is used in the email template
[16:00:53] Gazler: Separately, you probably shouldn't pass the entire conn to Accounts.refresh_email_auth_token.
[16:01:15] Gazler: Since it limits how you can use the function.
[16:01:18] nickjj: internally that function uses Phoenix.Token.sign and then updates a changeset+updates the repo
[16:01:49] nickjj: Phoenix.Token.sign needed the conn i think
[16:01:56] Gazler: Phoenix.Token.sign can take the endpoint instead.
[16:02:15] Gazler: Phoenix.Token.sign(MyApp.Endoint)
[16:02:30] nickjj: oh right, i'm using the endpoint directly in a test
[16:02:43] Nicd-: why is there a version that takes the conn then?
[16:03:12] Nicd-: so you can write endpoint agnostic code I guess
[16:03:15] nickjj: i'm not sure, i was kind of afraid of just blindly replacing conn with the endpoint in various spots
[16:03:19] Gazler: Backwards compatability too.
[16:03:53] Gazler: It can also take a socket
[16:03:58] Gazler: https://github.com/phoenixframework/phoenix/blob/94e851697a373eb5c98fd670bd7cadfb1524066c/lib/phoenix/token.ex#L193
[16:03:58] nickjj: so in this case, it's 100% safe to always use endpoint for the Phoenix.Token.x functions?
[16:04:44] Gazler: nickjj: Yeah, the conn code just looks up the endpoint first.
[16:04:46] nickjj: as in, remove the conn/endpoint as an argument and hardcore MyApp.Endpoint in that refresh function
[16:04:52] nickjj: *hardcode
[16:06:02] nickjj: and on that topic, is that a smart move? because if i do that, then suddenly the Account context (outside of Web) needs to know about MyApp.Endpoint
[16:06:22] Gazler: Glad you asked, I was about to say I'd avoid using Phoenix.Token altogether.
[16:06:29] Gazler: It already knows about your conn.
[16:06:40] Gazler: I don't know why you need to use Phoenix.Token though.
[16:06:59] nickjj: i thought it was the defacto standard way to generate tokens?
[16:07:43] nickjj: the token contains a unique identifier about the user, so that after they click the link in the email, i can sign them in
[16:08:09] Gazler: You can also pass the secret string directly by the way.
[16:08:17] nickjj: Phoenix.Token.sign/verify seemed to have all of the tools i needed to pull that off (tamper proof, supports a salt, deals with the gory bits of making the token and supports an expiration date)
[16:09:00] nickjj: what do you mean by that?
[16:09:38] Gazler: Phoenix.Token.sign("some_long_secret_string_here", "salt", data)
[16:10:05] Gazler: Phoenix uses Plug.Crypto for it, but to be honest, sometimes the convenience outweighs breaking the context rules.
[16:10:39] Gazler: If you wanted your context to be free from Phoenix, you could copy this code into your context https://github.com/phoenixframework/phoenix/blob/94e851697a373eb5c98fd670bd7cadfb1524066c/lib/phoenix/token.ex#L109
[16:12:32] nickjj: realistically i am developing a web app, so i don't mind breaking the rules maybe, but then i'm constantly reminded from that one pragmatic programmer tip about rocks and glass houses
[16:13:05] nickjj: once you break the rules, it's easy to talk to yourself into breaking another one and before you know it, you're living in a rat hole
[16:14:00] pera: has joined #elixir-lang
[16:16:15] Gazler: nickjj: If that bothers you, use plug_crypto directly, you won't have to copy much code.
[16:16:25] Gazler: Especially if you don't need to worry about supporting conn and sockets and Endpoint
[16:16:35] Gazler: You can just provide a secret directly.
[16:18:00] nickjj: appreciate the back and forth tho (both of you), refactoring code always feels good
[16:18:59] Gazler: nickjj: Shameless plug https://www.youtube.com/watch?v=V21DAKtY31Q
[16:19:31] nickjj: the one thing i don't get about your gist tho is...
[16:19:53] nickjj: how does lines 4-9 still have access to the user?
[16:20:15] Gazler: It doesn't, let me fix that. :)
[16:20:23] supercodepoet: has joined #elixir-lang
[16:20:28] Gazler: nickjj: https://gist.github.com/Gazler/a621c7af8da7a61786963c946086d154
[16:20:30] nickjj: and how does line 3 know deactivated_at should be checked on the user?
[16:20:43] nickjj: ah there we go
[16:20:58] Nicd-: it's a tuple where the second element is the user
[16:21:09] Gazler: Yeah, it's the response from your get_by_email function.
[16:21:12] griffinbyatt: has joined #elixir-lang
[16:21:20] nickjj: Nicd-, i mean in his gist originally before the edit
[16:21:24] Nicd-: it doesn't "know" it is the user, it just happens to be in that spot
[16:21:28] Nicd-: in that original gist too
[16:21:48] nickjj: originally it was {:ok, %{deactivated_at: nil}} -> but then it was changed to {:ok, %{deactivated_at: nil} = user} ->
[16:22:17] nickjj: i'll def. watch that video, thanks
[16:23:02] supercodepoet: has joined #elixir-lang
[16:23:03] Nicd-: in both it's matching a 2-tuple
[16:23:40] Nicd-: in the latter it's just capturing the whole value to a variable too
[16:23:50] Nicd-: the whole second element*
[16:24:36] nickjj: do you know the design decision on why the = user is last and not first?
[16:24:59] griffinbyatt: Pattern match can go either way
[16:26:00] nickjj: {:ok, user = %{deactivated_at: nil}} , for example, as a beginner this reads a little more naturally than {:ok, %{deactivated_at: nil} = user}
[16:26:18] notzmv: has joined #elixir-lang
[16:26:23] gazler_: has joined #elixir-lang
[16:26:25] griffinbyatt: Different strokes for different folks :)
[16:27:01] nickjj: i'll get used to it eventually, that is really awesome tho, i never knew you could pattern match to that degree
[16:27:18] supercodepoet: hello all, quick question I noticed with the release of ecto_sql 3.1.2 that the ensure_loaded function was remove from the Mix.EctoSQL module. Is there a recommended way now to endure the Repo is loaded in Mix tasks?
[16:34:37] wonko7: has joined #elixir-lang
[16:35:11] lexmag: has joined #elixir-lang
[16:42:21] lexmag: has joined #elixir-lang
[16:53:46] serafeim: has joined #elixir-lang
[16:57:07] fastfresh: has joined #elixir-lang
[16:58:25] hypercore: has joined #elixir-lang
[17:00:50] nickjj: Nicd-, mind looking at 1 more refactor? i used gazler's pattern in a different use case and it's working (passing tests) but still feels like maybe i'm doing it wrong
[17:07:38] lexmag: has joined #elixir-lang
[17:13:33] lexmag: has joined #elixir-lang
[17:19:07] lexmag: has joined #elixir-lang
[17:22:15] icecreamcohen: has joined #elixir-lang
[17:25:31] icecreamcohen: has joined #elixir-lang
[17:35:02] hypercore: has joined #elixir-lang
[17:38:49] lexmag: has joined #elixir-lang
[17:42:34] icecreamcohen: has joined #elixir-lang
[17:44:28] lexmag: has joined #elixir-lang
[17:45:13] icecreamcohen: has joined #elixir-lang
[17:45:16] supercodepoet: has joined #elixir-lang
[17:50:07] lexmag: has joined #elixir-lang
[17:52:48] lexmag: has joined #elixir-lang
[18:04:34] Poeticode: has joined #elixir-lang
[18:08:33] netrino: has joined #elixir-lang
[18:27:21] Phylock: has joined #elixir-lang
[18:27:33] mahmudov: has joined #elixir-lang
[18:40:55] kapilp: has joined #elixir-lang
[18:42:44] jeffro: has joined #elixir-lang
[18:54:29] netrino: has joined #elixir-lang
[18:54:47] squall: has joined #elixir-lang
[18:57:34] netrino_: has joined #elixir-lang
[18:58:07] pera: has joined #elixir-lang
[19:03:20] jeffro_: has joined #elixir-lang
[19:13:50] icecreamcohen: has joined #elixir-lang
[19:31:00] sacredfrog: has joined #elixir-lang
[19:34:56] serafeim: has joined #elixir-lang
[19:54:21] fastfresh: has joined #elixir-lang
[20:20:26] icecreamcohen: has joined #elixir-lang
[20:22:58] supercodepoet: has joined #elixir-lang
[20:35:10] warmwaffles: has joined #elixir-lang
[20:49:55] ur5us: has joined #elixir-lang
[21:06:06] ur5us: has joined #elixir-lang
[21:39:22] nickjj: damn too bad griffinbyatt left, what he said before was really eye opening, that totally shifts what i think about when i see = now
[21:39:28] nickjj: it's not an assignment, it's a pattern
[21:43:41] icecreamcohen: has joined #elixir-lang
[22:15:57] supercodepoet: has joined #elixir-lang
[22:16:06] supercodepoet: quick question I noticed with the release of ecto_sql 3.1.2 that the ensure_loaded function was remove from the Mix.EctoSQL module. Is there a recommended way now to endure the Repo is loaded in Mix tasks?
[22:21:03] linduxed: has joined #elixir-lang
[22:22:58] onto: has joined #elixir-lang
[22:25:41] onto: Hi! I am just learning elixir and I want to build a web service (using phoenix) that is delegating authentication and user data storage to different subsystems (called via HTTP APIs). What is a good way to organise this? Should a genserver be used (I think not, since I am not storing any state locally). Should it just be a module with methods that call the various endpoints?
[22:32:00] griffinbyatt: has joined #elixir-lang
[22:39:56] __charly__: has joined #elixir-lang
[22:41:08] proteusguy: has joined #elixir-lang
[22:52:38] supercodepoet: has joined #elixir-lang
[22:55:36] griffinbyatt: has joined #elixir-lang
[22:59:22] kyrylo: has joined #elixir-lang
[23:05:23] Sgeo: has joined #elixir-lang
[23:14:52] thomasross: has joined #elixir-lang
[23:17:58] duaneb: has joined #elixir-lang
[23:18:30] icecreamcohen: has joined #elixir-lang
[23:25:43] Cloudflare: has joined #elixir-lang