« Back to channel list

#elixir-lang - 22 May 2019

« Back 1 day Forward 1 day »
[00:06:17] wsieroci: has joined #elixir-lang
[00:06:36] netrino: has joined #elixir-lang
[00:08:26] asabil_: has joined #elixir-lang
[00:23:09] jeffro_: has joined #elixir-lang
[00:24:26] blahdodo: has joined #elixir-lang
[00:43:26] Adkron: has joined #elixir-lang
[00:45:38] netrino: has joined #elixir-lang
[00:55:27] oneark: has joined #elixir-lang
[01:00:14] wsieroci: has joined #elixir-lang
[01:17:03] ryotsu: has joined #elixir-lang
[01:24:37] netrino: has joined #elixir-lang
[01:39:09] tomterl: has joined #elixir-lang
[01:54:10] wsieroci: has joined #elixir-lang
[02:03:37] netrino: has joined #elixir-lang
[02:15:43] Adkron: has joined #elixir-lang
[02:18:35] icecreamcohen: has joined #elixir-lang
[02:42:41] netrino: has joined #elixir-lang
[02:45:10] blahdodo: has joined #elixir-lang
[02:45:55] demmark: has joined #elixir-lang
[02:48:10] wsieroci: has joined #elixir-lang
[02:49:27] Adkron: has joined #elixir-lang
[02:51:08] sevenseacat: has joined #elixir-lang
[03:21:40] netrino: has joined #elixir-lang
[03:23:01] icecreamcohen: has joined #elixir-lang
[03:28:34] Adkron: has joined #elixir-lang
[03:41:19] mdbm: has joined #elixir-lang
[03:42:08] wsieroci: has joined #elixir-lang
[03:43:07] kyrylo: has joined #elixir-lang
[04:00:23] Adkron: has joined #elixir-lang
[04:00:42] netrino: has joined #elixir-lang
[04:13:14] mbuf: has joined #elixir-lang
[04:36:01] wsieroci: has joined #elixir-lang
[04:39:44] netrino: has joined #elixir-lang
[04:41:27] kapilp: has joined #elixir-lang
[04:57:35] iFire: has joined #elixir-lang
[05:01:12] mdbm: has joined #elixir-lang
[05:11:11] Adkron: has joined #elixir-lang
[05:18:46] netrino: has joined #elixir-lang
[05:27:56] nikhilmore54: has joined #elixir-lang
[05:30:02] wsieroci: has joined #elixir-lang
[05:33:19] lackac: has joined #elixir-lang
[05:33:21] tnez: has joined #elixir-lang
[05:33:31] chops: has joined #elixir-lang
[05:33:34] tvon: has joined #elixir-lang
[05:33:34] Paradox: has joined #elixir-lang
[05:33:36] termos: has joined #elixir-lang
[05:33:41] Nicd-: has joined #elixir-lang
[05:33:48] HashNuke: has joined #elixir-lang
[05:33:56] oneark: has joined #elixir-lang
[05:34:00] Liothen: has joined #elixir-lang
[05:34:35] gausby_: has joined #elixir-lang
[05:34:44] dignifiedquire: has joined #elixir-lang
[05:35:10] fishcakez: has joined #elixir-lang
[05:50:57] Adkron: has joined #elixir-lang
[05:51:36] gvaughn: has joined #elixir-lang
[05:53:21] Mieserkadser: has joined #elixir-lang
[05:57:42] netrino: has joined #elixir-lang
[06:01:41] mdbm_: has joined #elixir-lang
[06:02:40] mdbm_: has joined #elixir-lang
[06:04:12] mdbm_: has joined #elixir-lang
[06:05:00] voltone: has joined #elixir-lang
[06:08:00] blahdodo: has joined #elixir-lang
[06:10:54] kdisneur: has joined #elixir-lang
[06:11:47] Mieserkadser: Is it possible to define multiple Join Functions inside a Channel-Implementation? So a join for room:dev, room:123, room:abc etc. ?
[06:17:35] mdbm: has joined #elixir-lang
[06:23:56] wsieroci: has joined #elixir-lang
[06:31:13] kdisneur: has joined #elixir-lang
[06:32:36] mdbm: has joined #elixir-lang
[06:34:02] netrino: has joined #elixir-lang
[06:34:49] asabil: has joined #elixir-lang
[06:34:52] OliverMT: Mieserkadser: the join function is just a function, if you pattern match it will behave differently
[06:35:02] OliverMT: as you'd expect for normal functions
[06:36:04] Mieserkadser: Make sense. A channel-module can implement multiple topics.
[06:36:54] OliverMT: it's more that the framework simply calls join/3
[06:37:05] OliverMT: and you can if you so choose implement multiple function heads for that function
[06:37:34] OliverMT: it's important to de-magicify the framework, thats why this is so much better than django, rails and all those magic black box thingies
[06:37:52] OliverMT: it's just a behaviour you're implementing and the framework calls your functions, no magic
[06:39:31] netrino_: has joined #elixir-lang
[07:01:26] jkva: has joined #elixir-lang
[07:05:27] Sgeo__: has joined #elixir-lang
[07:13:17] siwatpru: has joined #elixir-lang
[07:14:19] hypercore: has joined #elixir-lang
[07:18:12] lexmag: has joined #elixir-lang
[07:18:32] asabil: has joined #elixir-lang
[07:31:34] gvaughn: has joined #elixir-lang
[07:31:52] Sgeo_: has joined #elixir-lang
[07:37:48] Mieserkadser: What is the purpose of Plug if you can just write Functions to apply changes to Conn Struct?
[07:38:27] Sgeo_: has joined #elixir-lang
[07:49:06] kapilp: has joined #elixir-lang
[07:50:22] asabil: has joined #elixir-lang
[07:56:58] Adkron: has joined #elixir-lang
[07:58:11] netrino_: has joined #elixir-lang
[07:58:19] jeffweiss: has joined #elixir-lang
[08:07:16] netrino_: has joined #elixir-lang
[08:08:48] hypercore: has joined #elixir-lang
[08:12:13] weird_error: has joined #elixir-lang
[08:13:51] nikhilmore54: has joined #elixir-lang
[08:16:20] netrino_: has joined #elixir-lang
[08:28:43] gvaughn: has joined #elixir-lang
[08:33:39] dysfun: Mieserkadser: it provides both the conn struct and those functions so you don't have to write them?
[08:35:00] Adkron: has joined #elixir-lang
[08:43:35] jkva: I'm running a Phoenix app, `phoenix 1.4.6` and `cowboy 2.6.3`. I keep getting the error that 'module Plug.Cowboy is not available', where should I be looking to resolve this?
[08:44:33] dysfun: jkva: you didn't list plug_cowboy ?
[08:45:23] jkva: dysfun: by default it's not part of a generated phoenix app, it seems. I mean, it's not listed in the deps
[08:45:49] dysfun: *shrug* i haven't generated a new phoenix app since 1.4, but when i upgraded, i had to add it
[08:45:49] jkva: Hence I would think it's a dependency somewhere in Phoenix itself
[08:46:02] jkva: Ok, that's the easiest solution then
[08:46:35] jkva: Yeah, looks like 2.0.2 is latest so that looks good
[08:47:10] jkva: That sorted it. Weird I had to do that.
[08:47:43] dysfun: i can't speak for the template, but maybe it's old
[08:47:45] nikhilmore54: has joined #elixir-lang
[08:47:56] dysfun: maybe it's the phoenix 1.3 generator script?
[08:48:23] jkva: dysfun: could be, but a "fresh" generated app works. So probably something I futzed up somewhere
[08:48:34] dysfun: happens :)
[08:55:29] kyrylo_: has joined #elixir-lang
[08:55:43] netrino_: has joined #elixir-lang
[09:06:36] serafeim: has joined #elixir-lang
[09:08:03] gvaughn: has joined #elixir-lang
[09:09:38] koollman: has joined #elixir-lang
[09:12:14] DTZUZO_: has joined #elixir-lang
[09:16:26] kyrylo: has joined #elixir-lang
[09:17:52] Sgeo_: has joined #elixir-lang
[09:19:33] Sgeo__: has joined #elixir-lang
[09:34:42] netrino_: has joined #elixir-lang
[09:34:50] kdisneur: has joined #elixir-lang
[09:36:04] Mieserkadser: Phoenix: The controller has a pipeline where some plugs called. Why do i use a pipeline here? The Endpoint has also a set of Plugs. Couldn't use the Endpoint a pipeline as well?
[09:36:54] Mieserkadser: Or vice versa: Could a Controller just use plugs without a pipeline?
[09:38:13] Mieserkadser: As i understand the only difference is the order? So a pipeline need to apply the plugs as the defined while the endpoint defines plugs which are called from elsewhere
[09:39:03] serafeim: i think that the difference is the order and that the plugs that are defined in the endpoint will be applied to all routers and controllers
[09:41:07] serafeim: there seem to be 3 places you can apply plugs: endpoint > router pipeline > controller
[09:41:28] serafeim: depending on where you'll add it it will be more localized
[09:41:40] serafeim: it's very simple actually
[09:42:14] serafeim: if you keep in mind the actual functionality of the plug: just change conn by adding / removing / updating some if its attrs
[09:43:27] Gika: has joined #elixir-lang
[09:45:22] Mieserkadser: Yeah, pretty simple. Ty
[09:47:41] lexmag: has joined #elixir-lang
[09:49:54] Mieserkadser: How does the PageController now how's name of the template app.html of the LayoutView? Is it part of the Information stored in Conn? It's kind of magic for me.
[09:51:09] Mieserkadser: If i call render inside my controller with the corresponding template name i expect that only that part i gonna be rendered. Instead there is a bunch of other things happening in the background like rendering LayoutView.
[09:53:57] Gika: hi, i'm trying to figure out the "zipper" exercise on exercism, which requires me to transform a rose tree into a zipper, but i'm having problems starting up. i have to implement a `from_tree` function (@spec from_tree(BinTree.t()) :: Zipper.t()) and the corresponding `to_tree` function, but while the type spec for BinTree is provided (%BinTree{value: any, left: t() | nil, right: t() | nil}), the Zipper type is not, so while i guess
[09:53:57] Gika: it's up to me to create it, i'm not really sure what it should look like, or even why it should be different from the BinTree type... i mean why not use the BinTree directly to implement the other operations? maybe i'm missing the point
[09:58:27] serafeim: Mieserkadser if you take a look at the phoenix controller __using__ you'll see the following line plug :put_new_layout, {Phoenix.Controller.__layout__(__MODULE__, opts), :app}
[09:58:52] kyrylo: has joined #elixir-lang
[09:59:36] serafeim: this line is included in your code from the "using ProjectWeb :controller" line; that's the one that sets the layout
[10:00:26] serafeim: https://hexdocs.pm/phoenix/Phoenix.Controller.html#put_new_layout/2
[10:04:13] gvaughn: has joined #elixir-lang
[10:37:59] jkva: `case/do` syntax has me a bit confused -- can I use a block (multiple statements) after a `->` or should I use different flow control for that?
[10:40:37] siwatpru_: has joined #elixir-lang
[10:40:49] Nicd-: you can use multiple statements
[10:41:13] Adkron: has joined #elixir-lang
[10:43:21] fastfresh: has joined #elixir-lang
[10:43:44] jkva: I'll try that with a `do/end` block
[10:44:10] Nicd-: try what?
[10:45:33] jkva: I worded my question poorly. Can I use multiple expressions in a case/do block?
[10:48:05] jkva: Doesn't seem to, at least
[10:48:52] Nicd-: after `->` yes you can
[10:50:34] Nicd-: see here for example: https://gitlab.com/code-stats/code-stats/blob/master/lib/code_stats_web/controllers/auth_controller.ex#L112-118
[10:51:23] jkva: Ah, ok. I hadn't found any examples doing that. Thanks!
[11:08:16] lexmag: has joined #elixir-lang
[11:11:15] gvaughn: has joined #elixir-lang
[11:13:04] kdisneur: has joined #elixir-lang
[11:17:31] Adkron: has joined #elixir-lang
[11:26:30] za1b1tsu: has joined #elixir-lang
[11:39:33] tnez: has joined #elixir-lang
[11:44:39] kyrylo: has joined #elixir-lang
[11:45:31] lexmag: has joined #elixir-lang
[11:48:16] netrino_: has joined #elixir-lang
[11:50:22] griffinbyatt: has joined #elixir-lang
[11:50:57] gvaughn: has joined #elixir-lang
[12:10:45] sirn: has joined #elixir-lang
[12:13:46] lauromoura_: has joined #elixir-lang
[12:22:08] MissingNoIOI: has joined #elixir-lang
[12:22:33] dysfun: jkva: huh? you'd only seen cases that do one match?
[12:22:43] dysfun: a case that only does one match may as well be an =
[12:23:24] dysfun: ohhh, now i get it
[12:26:58] tallysmartins_: has joined #elixir-lang
[12:27:17] netrino_: has joined #elixir-lang
[12:47:06] lexmag: has joined #elixir-lang
[12:49:51] serafeim: has joined #elixir-lang
[13:06:21] netrino_: has joined #elixir-lang
[13:07:02] knack: has joined #elixir-lang
[13:15:54] nickjj: this is more of a db question i suppose, but if you had 2 foreign keys on a table and you made a unique_index on them, would you still want to create a regular index on each individual FKs if you planned to filter on them individually?
[13:22:39] __charly__: has joined #elixir-lang
[13:23:13] proteusguy: has joined #elixir-lang
[13:23:45] lexmag: has joined #elixir-lang
[13:23:46] Adkron: has joined #elixir-lang
[13:24:54] BitBot: has joined #elixir-lang
[13:28:36] fastfresh: has joined #elixir-lang
[13:30:10] gvaughn: has joined #elixir-lang
[13:31:31] voltone: has joined #elixir-lang
[13:32:34] rbino: best source of bike-shedding in Elixir land: "Which http client library do I use for this project?"
[13:35:31] benwilson512: OK I'm probably missing something obvious, URL query parameters show up in a live view where?
[13:36:02] josevalim: benwilson512: not yet
[13:36:08] josevalim: it is coming soon or maybe already in a branch
[13:36:14] josevalim: summon chrismccord
[13:36:29] benwilson512: URL query parameters
[13:36:33] josevalim: for Live View
[13:36:45] benwilson512: I've got a search button in the top right corner I want to route to a live view w/ the contents in the URL
[13:37:04] benwilson512: button itself is 100% normal "go to this path"
[13:37:04] josevalim: chrismccord: do you have the table example still up and running?
[13:37:10] lexmag: has joined #elixir-lang
[13:37:10] chrismccord: I am working on it as we speak
[13:37:22] chrismccord: there will be a handle_params callback
[13:37:36] chrismccord: josevalim : I am like 15 layers deep in javascript race conditions
[13:37:47] benwilson512: ok. I guess in the meantime I can shove it in the assigns from a plug or something
[13:37:49] chrismccord: fuck mutability
[13:37:58] josevalim: chrismccord: language pls
[13:38:02] chrismccord: also phoenix is too fast
[13:38:19] benwilson512: chrismccord forgot this wasn't a DM ;)
[13:38:57] chrismccord: there was a race with the push state where I was pushing a message up the channel and updating browser pushstate on the resp
[13:39:33] chrismccord: referencing window.location.path in a callback, which of course is mutable
[13:39:48] benwilson512: chrismccord: to be clear, I'm not trying to change the URL from within live view, although that'll probably be the thing I need later
[13:40:17] josevalim: benwilson512: so you need to get the parems and put it in the session
[13:40:19] chrismccord: benwilson512 : gotcha. So I am working on a unified callback
[13:40:25] josevalim: but the upcoming version will have a callback for it
[13:40:30] josevalim: which can be used for that and for live links
[13:40:39] chrismccord: it will work for pushstate, updating from the LV, and for your query param case
[13:40:51] chrismccord: and for sending arbitrary client specific data from the js side to the lv
[13:40:53] josevalim: one callbaack to bind them all
[13:41:14] chrismccord: but *today*, you can grab out the specific query params and put the in the session
[13:41:17] josevalim: the extra a was courtessy of my fantastic mac keyboard
[13:42:12] benwilson512: while you're here, has anyone else reported an issue with live view and form drop down boxes?
[13:42:33] gvaughn: has joined #elixir-lang
[13:43:25] benwilson512: at the moment it's completely static html
[13:43:29] benwilson512: https://www.irccloud.com/pastebin/Brtgo6pS/
[13:43:48] benwilson512: but simply within a live view. it exhibits two weird behaviours
[13:43:58] josevalim: i think scott fixed some things related to this?
[13:44:12] benwilson512: ah let me update
[13:44:14] josevalim: i would make sure i am on latest and nuke node_modules to forice it to rebuild just in case
[13:45:25] benwilson512: that did it, my bad
[13:45:31] Adkron: has joined #elixir-lang
[13:46:37] benwilson512: josevalim chrismccord the product we built with live view made such an impression the folks we demoed it to came back the next day wanting to license it, so thanks!
[13:46:53] chrismccord: benwilson512 : that's incredible!!
[13:49:20] blahdodo: has joined #elixir-lang
[13:52:58] blahdodo: has joined #elixir-lang
[13:54:45] benwilson512: so, the tricky bit of using the conn assigns is that I have to get the url params with assign_new
[13:54:52] benwilson512: and in that case there's no sensible function I can supply
[13:55:22] benwilson512: and I'd rather not put them in the conn session, that's gonna get messy
[13:56:10] benwilson512: might just violate socket privacy
[13:56:21] josevalim: benwilson512: wjhy assign_new? assign_new would rather be used to load data based on the session params/query params
[13:56:41] benwilson512: josevalim: conn |> assign(:foo, "bar") in a plug doesn't show up as an assign in the socket
[13:56:46] benwilson512: if using live router
[13:57:46] benwilson512: I'm missing some aspect of the proposed work around for the url parameters thing then
[13:58:05] benwilson512: I was planning on conn |> assign(:url_params, conn.params) and then accessing that in the socket somewhere
[13:59:31] josevalim: you need to do
[13:59:50] josevalim: live_render(MYLiveThing, session: %{query_params: conn.query_params}})
[13:59:52] josevalim: or something like that
[14:00:17] josevalim: or you can have a plug in your router that puts it as :url_params
[14:00:28] josevalim: and then in the live router call you pass session: [:url_params]
[14:00:30] josevalim: or something like that
[14:00:45] benwilson512: session looks at the conn session not the conn assigns
[14:00:50] benwilson512: but stepping back for a second
[14:01:07] benwilson512: if I'm using live "/path", SomeView in the router, what am I supposed to have in app.html.eex?
[14:01:12] benwilson512: I still have the traditional <%= render @view_module, @view_template, assigns %>
[14:02:33] benwilson512: "you can have a plug in your router that puts it as :url_params" this is what I do. session: [:url_params] doesn't pull it in, I think it just looks at the session
[14:05:53] benwilson512: notably I'm running on this branch https://github.com/phoenixframework/phoenix_live_view/pull/211/files merged w/ phoenix_live_view master otherwise I couldn't get app.html.eex to render at all
[14:07:52] netrino_: has joined #elixir-lang
[14:11:42] benwilson512: https://github.com/phoenixframework/phoenix_live_view/blob/master/lib/phoenix_live_view/plug.ex#L29
[14:14:06] Adkron: has joined #elixir-lang
[14:19:17] hypercore: has joined #elixir-lang
[14:22:30] serafeim: has joined #elixir-lang
[14:27:14] benwilson512: ah, updating phoenix live view fixed the drop down not having an immediate value, but if you click on it it still spazzes out
[14:27:25] benwilson512: investigating
[14:29:50] PragTob: has joined #elixir-lang
[14:43:01] kdisneur: has joined #elixir-lang
[14:44:12] kdisneur: has joined #elixir-lang
[14:46:52] netrino_: has joined #elixir-lang
[14:48:23] nickjj: does anyone know how to get a unique_constraint working on a changeset that involves multiple columns?
[14:48:58] nickjj: some answer on SO says this should work: |> unique_constraint(:user_id, name: :enrollments_user_id_package_id_index) -- however, ecto is always reporting this as valid when there's really a unique conflict
[14:49:37] nickjj: if i remove the constraint from the changeset then ecto rightly blows up saying there's a constraint at the database level , so i believe the unique index is set up correctly at the db level
[14:50:26] benwilson512: nickjj: uniq_constraint(:table, [:column1, :column2])
[14:50:32] nickjj: the behavior i'm getting with the above unique constraint is ecto says it's valid but the record doesn't get created or updated if it already exists
[14:50:36] benwilson512: you mean in the changeset
[14:51:00] nickjj: yeah the migration i set up exactly how you have it ben
[14:51:19] benwilson512: nickjj: unique_constarint doesn't actively check that it's unique, it means that after `Repo.insert` it will return a changeset that shows that it's invalid
[14:51:33] benwilson512: unique_constraint basically just catches a failed insert
[14:51:40] benwilson512: that's the only way to do so reliably without race conditions
[14:52:08] nickjj: what is a failed insert -- you mean the ecto error saying the DB says there's a unique index (a 500)?
[14:52:09] blassin42: has joined #elixir-lang
[14:52:24] blassin42: Twitter poll about a conference in Lisbon next year! https://twitter.com/LisbonElixir/status/1131208080778301440
[14:52:25] benwilson512: ignore http stuff for a second
[14:52:31] work_: has joined #elixir-lang
[14:52:45] nickjj: the error it reports says to prevent this problem, i should add a unique_constraint/3 to my changeset
[14:52:59] benwilson512: nickjj: if you have `thing |> unique_constraint()`, ecto has no idea if it's unique or not yet
[14:53:01] benwilson512: but then if you do
[14:53:08] benwilson512: `thing |> unique_constraint |> Repo.insert`
[14:53:30] benwilson512: it tries to insert, the insert fails, it checks the failure message against the unqiue_constraint name, and goes "cool, I know how to handle this"
[14:53:36] josevalim: nickjj: uniqueness checks can only be done by the database. Check the changeset docs for Ecto, it has an explanation on constraints vs validations
[14:53:37] nickjj: so i have to call the changeset twice?
[14:53:39] benwilson512: and then `Repo.insert` returns `{:error, changeset}`
[14:53:57] benwilson512: if you want to insert or update without race conditions yes
[14:54:03] benwilson512: alternatively you can upsert
[14:54:07] benwilson512: `on_conflict` etc
[14:55:06] nickjj: hmm, this is a really big monkey wrench and how i have things set up
[14:55:42] benwilson512: nickjj: that's literally the only way to guarantee uniqueness
[14:55:46] nickjj: because i initially run things through a changeset, to see if it's valid -- and then if it's valid, i move onto the next set of validations
[14:56:01] benwilson512: well, imagine if unique_constraint checked the database at the moment you called it
[14:56:08] nickjj: but it's sounding like foreign_key_constraint is also not even being checked in that first changeset run
[14:56:13] benwilson512: that's correct
[14:56:17] benwilson512: what would happen if between that moment and the Repo.insert call a record was added?
[14:56:41] nickjj: which is super misleading because ecto doesn't let you know about this, it just happily works without an issues or validation warnings
[14:56:48] benwilson512: it's in the docs
[14:57:11] benwilson512: https://hexdocs.pm/ecto/Ecto.Changeset.html#unique_constraint/3
[14:57:14] benwilson512: it describes the whole process
[14:57:23] benwilson512: > Now, when invoking Repo.insert/2 or Repo.update/2, if the email already exists, it will be converted into an error and {:error, changeset} returned by the repository. Note that the error will occur only after hitting the database so it will not be visible until all other validations pass.
[14:58:21] serafeim: I know that render_existing can be used on my layout to display stuff on a per-view basis; however I'd like to display stuff on a per-controller-action basis (i.e only display a <script> on my update/create actions). is there a way to do that ?
[14:58:26] lexmag: has joined #elixir-lang
[14:59:51] serafeim: i know that this can be done just be adding some loose <script> tags in my action template, however I'd really like to put these <script> tags on their corresponding place (after the </body>)
[15:02:30] serafeim: this can be done in django by overriding template blocks or in sitemesh by adding a decorator property: https://stackoverflow.com/questions/19111545/sitemesh-custom-javascript-per-page/19117252#19117252
[15:02:44] nickjj: benwilson512, to get around this, do you typically end up having a bunch of if statements in your control to validate things at multiple levels? (before the db write is even potentially going to happen and then again after to see the result)?
[15:04:00] nickjj: *control = controller
[15:07:33] nickjj: i think i'm missing something obvious because i don't think it's possible for me to accomplish what i'm trying to do if i have to attempt to insert something to detect if it's valid
[15:08:07] nickjj: because i don't want the record to be inserted (even if it's valid) until many unrelated events are successful
[15:08:33] nickjj: but i don't want those unrelated events to occur until i know for 100% sure that the thing would be inserted correctly -- i'm stuck in a loop
[15:15:21] benwilson512: nickjj: no, I never check `valid?` before `Repo.insert`
[15:15:32] benwilson512: nickjj: put it in a transaction
[15:15:49] benwilson512: insert all the things, if you hit something that is bad, rollback the whole transaction
[15:15:59] nickjj: benwilson512, what happens if you do need to check if it's valid before you try to insert?
[15:16:11] benwilson512: why do I need to do that?
[15:16:53] nickjj: let's say you're on a checkout page which is responsible for maybe creating a user, having a product_id and also processes payments
[15:17:13] nickjj: and the thing you're buying creates an "enrollment" (which ties in that user and the product)
[15:17:41] nickjj: you wouldn't want to create the enrollment until you know for sure the user exists, the product exists and a payment was successful through stripe/etc.
[15:18:13] nickjj: so the enrollment could have a FK and unique constraint on the user/product, but these don't get checked until you actually do a repo insert on enrollment
[15:18:36] nickjj: but you don't want to enroll them until you make a payment , but you don't want to make a payment until you know for sure the user and product are valid (but you can't do this without inserting first)
[15:18:40] nickjj: it's some type of loop
[15:19:53] benwilson512: there's sort of two separate things happening here
[15:19:58] benwilson512: 1) figure out if the user and product exists
[15:20:08] benwilson512: 2) ensure that this is a unique enrollment between the user and product
[15:20:43] benwilson512: the part that makes this hard is the API call to Stripe really
[15:20:52] nickjj: yep and 3) only allow a payment if #2 is valid, without actually doing the insert because the "real" enrollment happens after the payment is done
[15:21:06] benwilson512: right, and I think that modeling is by definition a catch 22
[15:21:09] nickjj: because they shouldn't be enrolled if the payment from stripe fails
[15:21:13] benwilson512: you need to create the enrollment in a pending state
[15:21:20] benwilson512: if that works, then make the stripe call
[15:21:24] benwilson512: if that works, set the state to confirmed
[15:21:59] nickjj: a workaround i was thinking of would be to have a bunch of if statements that do a repo get on the user / product -- to make sure they exist
[15:22:19] benwilson512: sure but that isn't perfect, they could be deleted after those checks and before your insert
[15:22:33] benwilson512: however yeah I usually do something like
[15:22:34] nickjj: and if the user exists and the product exists and the user is not already enrolled (another repo get) THEN make the payment and that's successful then enroll them
[15:23:03] benwilson512: https://www.irccloud.com/pastebin/aw978O71/
[15:23:16] nickjj: right, then somehow all of that would need to be wrapped in a transaction
[15:23:17] benwilson512: nickjj: all of that is fine, but it just permits race conditions is all
[15:23:31] benwilson512: becaues you can't transaction Stripe
[15:24:32] nickjj: does your pastebin get around the condition?
[15:24:40] nickjj: i've never seen that pattern yet
[15:24:44] benwilson512: not sure I follow
[15:25:31] nickjj: i'm not even sure what to ask to understand that pastebin haha
[15:25:45] nickjj: would the find_product only happen if find_user is successful?
[15:26:08] benwilson512: https://hexdocs.pm/elixir/Kernel.SpecialForms.html#with/1 with rocks
[15:26:15] nickjj: what happens if find_user fails? how would the error be presented/caught?
[15:26:41] benwilson512: `with` is just a fancier `case`
[15:26:44] nickjj: because ideally i will respond with different flash messages depending on what went wrong
[15:26:44] Saukk: has joined #elixir-lang
[15:26:49] benwilson512: docs have examples
[15:27:06] benwilson512: your `find_user` function would return something like `{:ok, user}` or `{:error, :no_user}`
[15:27:17] nickjj: but all of this isn't the "good" solution since it's not in a transaction?
[15:27:36] benwilson512: the transaction only matters if you're inserting multiple things, wasn't sure if you were doing that or not
[15:27:44] benwilson512: your transaction would either go around all of this
[15:27:44] nickjj: or is a transaction not possible due to stripe?
[15:27:59] benwilson512: a transaction will make sure that any database changes fail or succeed together, it does not help with stripe
[15:28:07] wsieroci: has joined #elixir-lang
[15:28:08] benwilson512: IE if the payment goes through
[15:28:09] nickjj: because i'm only inserting the enrollment as 1 db record (potentially the user beforehand but i think i'm ok with that not being in a transaction)
[15:28:11] Phylock: has joined #elixir-lang
[15:28:12] benwilson512: but your enrollment insert fails
[15:28:31] benwilson512: the payment won't be rolled back automatically
[15:28:44] benwilson512: that's why inserting the enrollment first in a pending state is so important
[15:28:45] nickjj: yeah, i really liked your idea of having a :status on the enrollment
[15:28:56] benwilson512: it's also great cause if stripe goes down
[15:29:01] benwilson512: you can process orders after the fact
[15:29:18] benwilson512: if the stripe call fails, you can rollback the transaction and the enrollment isn't saved
[15:29:20] benwilson512: up to you how to handle that
[15:29:47] nickjj: but if stripe isn't possible to be put into the transaction, how could i rollback the transaction?
[15:30:40] benwilson512: apologies, what I meant is that after the stripe call, if it fails, you can delete the enrollment
[15:31:10] nickjj: oh, yeah that makes sense
[15:31:27] nickjj: then i can keep the unique index as it is
[15:31:47] benwilson512: you try to insert the enrollment , if it fails, some other request is already handling this or already handled it
[15:31:56] benwilson512: if it succeeds, yay, it's your job to hit stripe
[15:32:15] benwilson512: if that succeeds, update the enrollment status, if it fails, delete it, so you can try again later
[15:33:01] benwilson512: transaction here is only important if either the enrollment insertion or deletion needs to be paired with other DB requests.
[15:34:22] kdisneur: has joined #elixir-lang
[15:37:32] nickjj: benwilson512, thanks a lot, totally makes sense
[15:38:03] nickjj: for clarity, this is the flow right? https://gist.github.com/nickjj/35567aeeabdcdc02d6d206e35b8492ad
[15:38:24] nickjj: and with the above flow, having to .valid? before inserting or rig a bunch of conditionals goes away
[15:39:20] nickjj: beautiful, the status was the missing link and thinking back now is a very nice thing to have in general
[15:40:37] netrino_: has joined #elixir-lang
[15:45:20] Sgeo__: has joined #elixir-lang
[15:52:32] aalmazan: has joined #elixir-lang
[15:52:35] icecreamcohen: has joined #elixir-lang
[16:02:34] tsu: has joined #elixir-lang
[16:03:28] river: has joined #elixir-lang
[16:03:29] nikhilmore54: has joined #elixir-lang
[16:05:00] river: Hi! Anyone here have experience using websocket with Phoenix?
[16:05:17] chrismccord: river some. What's up?
[16:05:47] Nicd-: "some" :D
[16:08:01] snapet: has joined #elixir-lang
[16:08:04] river: So we're using ember on the frontend, Phoenix on the backend. On the ember side we're using a library that's just a wrapper for Phoenix's client js library. One odd thing we noticed is that when the Phoenix js library is sending a heartbeat message, the client is unable to receive any new messages from the server.
[16:09:17] chrismccord: river : hearbeats are "normal" messages up the socket, so nothing special there. Do you mean messages appear to be "blocked", but then continue to work after the hearbeat, or the heartbeat appears to fail the app?
[16:10:20] river: Yes they continue to work after the heartbeat. We're using websocket for like a progress update, 1%, 2%, 3%... so there's like a gap for like 3 seconds whenever a heartbeat is sent
[16:13:43] Gika: has joined #elixir-lang
[16:17:45] chrismccord: river it sounds like an ember client thing. I would start there
[16:18:16] chrismccord: a heartbeat doesn't block anymore than anther other message, and it's also the cheapest message the server handles, since it's an immediate ack with no computation, so something else must be up
[16:18:53] chrismccord: river : can you also verify that the connection isn't dropping? Does this happen in dev, prod, or both?
[16:18:59] river: Right that's what I'd figured.
[16:19:35] river: The connection seems to be fine.
[16:19:41] netrino_: has joined #elixir-lang
[16:19:46] river: Happens on both
[16:21:54] feld: has joined #elixir-lang
[16:21:56] river: Well actually sorry I take that back. It doesn't happen locally.
[16:22:43] feld: any of the Phoenix crew in here?
[16:22:43] Gazler: river: Where is it deployed?
[16:22:51] feld: Trying to figure out if Nginx or Phoenix is at fault here
[16:23:04] Gazler: feld: nginx. Next question.
[16:23:06] feld: "Looks like the problem is that nginx doesn’t set a correct range for the last chunk: it rounds it up to the slice size (which is 1m in our config). So for the last slice of a 1,5mb file nginx will set `Range: 1048575-2097150`."
[16:23:07] Gazler: feld: What's the issue?
[16:23:08] chrismccord: hopefully ngnix so we don't have any work to do
[16:23:13] chrismccord: gazler is on it! haha
[16:23:49] Gazler: feld: Have you tried bypassing nginx and connecting directly to Phoenix to see if the same thing happens?
[16:24:21] river: It's deployed on Google Cloud
[16:26:51] feld: gazler: how would I simulate Nginx's reverse proxy slicing without using Nginx's code? :)
[16:27:33] Gazler: feld: That is a good question.
[16:28:36] feld: The reverse proxy slicing has no problem with other HTTP backends like Mino/Ceph, etc
[16:28:55] feld: but files > slice size get served truncated when they come from Phoenix / Plug.static
[16:30:29] feld: minibikini in here knows more details
[16:31:03] Gazler: feld: If you can post a sample application that shows off the issue I can take a look.
[16:37:58] Gazler: feld: What version of cowboy/plug_cowboy are you using?
[16:40:19] feld: {:plug_cowboy, "~> 2.0"},
[16:41:22] feld: gazler: this is easily reproduced with develop branch of Pleroma https://git.pleroma.social/pleroma/pleroma
[16:41:41] Gazler: Experimental range support was only added to cowboy recently according to https://ninenines.eu/docs/en/cowboy/2.6/guide/migrating_from_2.5/
[16:41:45] feld: enable mediaproxy, use sample nginx config, upload file larger than 1MB, try to view it in the app.
[16:42:02] feld: "so Pleroma accepts a request with invalid range but replies with a full file and 200. nginx apparently expect only 206 and can’t handle 200 in the situation"
[16:42:22] Gazler: I have to go, I'll take a look later. Please link to the nginx config
[16:43:09] feld: gazler: https://git.pleroma.social/pleroma/pleroma/blob/develop/installation/pleroma.nginx
[16:44:00] minibikini: So we have a 1.5mb file, nginx requests a first chunk 0-1mb, gets 206, then it requests the last chunk 1-2mb but Plug.Static responses with 200 and full file which nginx can't properly handle in this situation:
[16:44:00] minibikini: 2019/05/22 23:15:11 [error] 2970#0: *2425 unexpected status code 200 in slice response while reading response header from upstream, client: ::1, server: localhost, request: "GET /media/d8883d2112a1d40ac423a02346806de7f7aa786c6da9d00fbbd6eb03ad50d05f.png?name=test.11.png HTTP/1.1", subrequest: "/media/d8883d2112a1d40ac423a02346806de7f7aa786c6da9d00f
[16:44:00] minibikini: bbd6eb03ad50d05f.png", upstream: "", host: "localhost:4000"
[16:44:01] minibikini: Plug.Static expects the range to be < file length: https://github.com/elixir-plug/plug/blob/v1.8.0/lib/plug/static.ex#L272
[16:46:32] feld: I haven't crawled through the RFCs yet to see if sending a 200 in response to an invalid range request is permitted, or just something that browsers happen to accept
[16:49:12] nickjj: benwilson512, do you have a public site or twitter account? asking because if i do a write up on this checkout code, i'd like to link to you about the status idea
[16:50:51] lexmag: has joined #elixir-lang
[16:50:58] Nicd-: so is it safe to go with postgrex 1.0.0 rc1?
[16:51:26] Nicd-: I reckon the API is compatible
[16:52:13] Nicd-: oh, ecto demands 0.14.0
[16:53:50] feld: https://tools.ietf.org/html/rfc7233#section-4.4
[16:55:29] feld: I think the Note at the end of section 4.4 puts the blame on Nginx
[16:56:17] feld: Phoenix could fix this by responding with a 416, but Nginx should be accepting the 200
[17:01:24] drrty: has joined #elixir-lang
[17:03:56] netrino_: has joined #elixir-lang
[17:12:26] wsieroci: has joined #elixir-lang
[17:14:32] blahdodo: has joined #elixir-lang
[17:23:37] eudocimus_r: has joined #elixir-lang
[17:30:18] Gika: has joined #elixir-lang
[17:32:58] blahdodo: has joined #elixir-lang
[17:39:07] josevalim: micmus, nox: do you know if there is something that converts all beam chunks into erlang terms?
[17:40:33] josevalim: feld: please open up an issue in plug, i think returning 416 would be better
[17:40:43] josevalim: feld: a PR would also be welcome, i will be glad to hlp if you havee any questions
[17:45:11] micmus: josevalim: I don't think there is, no. I guess beam_lib:chunks listing all known chunks with the allow missing option could be useful in some cases
[17:47:16] josevalim: micmus: so a follow up question is if we could use any of the chunks to rebuild all external calls with line numbers?
[17:47:28] josevalim: there is a chunk for external calls but no line numbers unfortunately
[17:48:03] Gika: has joined #elixir-lang
[17:49:00] micmus: josevalim: I'm not sure I follow. In general line numbers are embedded as references to the location table inside of the bytecode instructions
[17:54:29] josevalim: micmus: i would like to extract from .beam all remote calls that module does
[17:54:58] josevalim: and I can do that looking at the ImpT chunk. but that chunk does not include where the calls happen
[17:56:00] micmus: yeah, you'd probably need to traverse the bytecode for that
[17:57:04] Kerem: has joined #elixir-lang
[17:57:04] josevalim: feld: actually, i can see the issue with not serving anything on an invalid range :(
[17:57:58] netrino_: has joined #elixir-lang
[17:58:38] Kerem: A quick google search did not yield any results; Is there a way of checking in a guard against the binary_id type from ecto?
[18:00:13] Nicd-: what is the corresponding type in Elixir?
[18:00:18] josevalim: Kerem: to check if it is valid? not possible
[18:00:30] josevalim: to check if it is a binary_id, then is_binary/1 should do it
[18:01:04] squalloster: has joined #elixir-lang
[18:01:43] ericmj: feld: if nginx only accepts 206 to a range request then nginx is at fault
[18:02:02] ericmj: you should be expected to handle a 200 response on a range request
[18:02:05] Kerem: Hmm but as i understand it is_binary is an actual binary not the binary_id e.g. uuid in ecto
[18:02:26] Nicd-: I think its type in Elixir is a binary
[18:03:11] ericmj: yes, ecto's binary_id is of the binary type in elixir
[18:03:17] benwilson512: Kerem: guards only really apply to fundamental VM types
[18:04:18] Kerem: Ahh right, altough my memory may be wrong here 5+ years since i coded in Erlang, but you could create your own guards based on arbitrary logic (It is possible im quite wrong here!!!)
[18:04:42] Nicd-: that's not possible in Elixir or Erlang
[18:04:43] ericmj: you can use is_binary + byte_size
[18:05:19] Nicd-: you can create your own guards but only by combining specific calls that are already allowed in guards
[18:05:20] ericmj: `defguard is_binary_id(arg) when is_binary(arg) and byte_size(arg) == 8`
[18:05:30] ericmj: (I think byte_size is 8 for binary_id)
[18:07:11] Kerem: yea! your probably right, my memory does not serve me well.
[18:07:48] Nicd-: by appeal to authority, they are right :D
[18:25:55] jnoon2: has joined #elixir-lang
[18:36:28] netrino_: has joined #elixir-lang
[18:37:58] Saukk: has joined #elixir-lang
[18:46:32] nickjj: is there a more elegant way to write this find_or_create_user function? https://gist.github.com/nickjj/76b78b790e3c9c61e39ff3bcddf0d233
[18:47:05] nox: josevalim: Sorry I was at my theatre class.
[18:47:09] nox: ACTION just loves saying that.
[18:47:36] nox: josevalim: The line number shit AFAIK is only read by the VM, and the code using it is in C.
[19:03:09] jkva: I've been wondering why I don't need to entirely mention a controller completely by its namespace when defining a route in Phoenix. As in `App.Controller` should be used as `Controller`. Is this some convention I'm unaware of? There seems to happen some automatic namespacing somewhere.
[19:12:51] pera: has joined #elixir-lang
[19:14:58] m1dnight_: okay guys, I just submitted a paper to middleware. Im going to procrastinate like crazy. Give me a PR to fix!
[19:15:06] m1dnight_: or, otherwise, hey all
[19:18:55] blahdodo: has joined #elixir-lang
[19:19:38] m1dnight_: damn, no issues on elixir :p
[19:19:41] m1dnight_: what is this for perfect language
[19:27:19] m1dnight_: I've been hacking together a website with a remote repl to dockers running iex
[19:27:24] m1dnight_: but im kind of sick of that
[19:27:38] m1dnight_: I really want to contribute to some open source
[19:27:51] m1dnight_: but i feeltoo dump for most of them
[19:38:26] benwilson512: jkva: that's why scope helps with that
[19:39:05] jkva: Aaaah riiight
[19:39:08] jkva: Why didn't I see that
[19:39:14] jkva: Thanks benwilson512
[19:39:22] jkva: It was right in front of my nose
[19:48:17] _barcode_: has joined #elixir-lang
[20:31:03] mahmudov: has joined #elixir-lang
[20:56:52] pera: has joined #elixir-lang
[21:01:03] jeffro_: has joined #elixir-lang
[21:05:17] Exuma: has joined #elixir-lang
[21:07:27] ephemera_: has joined #elixir-lang
[21:23:11] blahdodo: has joined #elixir-lang
[21:24:54] drincruz: has joined #elixir-lang
[21:29:24] pera: has joined #elixir-lang
[21:31:51] gvaughn: has joined #elixir-lang
[21:43:01] blahdodo: has joined #elixir-lang
[21:58:45] laut: has joined #elixir-lang
[22:04:39] __charly__: has joined #elixir-lang
[22:19:38] garazdawi: has joined #elixir-lang
[22:25:46] gvaughn_: has joined #elixir-lang
[22:29:29] nickjj: does elixir have an alternative way to handle things like `pass` in other languages, or basically saying "this condition should be documented but it actually does nothing"?
[22:29:56] nickjj: couldn't find this in the docs or in any code bases i looked at, makes me think maybe it's not available but how do you guys deal with that?
[22:50:44] pera: has joined #elixir-lang
[23:10:30] praveenperera: has joined #elixir-lang
[23:12:30] weird_error: has joined #elixir-lang
[23:20:04] Cloudflare: has joined #elixir-lang
[23:21:03] weird_error: has joined #elixir-lang
[23:36:46] netrino_: has joined #elixir-lang
[23:38:11] jnoon2: has joined #elixir-lang
[23:46:01] netrino_: has joined #elixir-lang
[23:55:07] netrino_: has joined #elixir-lang