« Back to channel list

#elixir-lang - 19 June 2019

« Back 1 day Forward 1 day »
[00:11:01] orbyt_: has joined #elixir-lang
[00:15:25] jnoon2: has joined #elixir-lang
[00:23:51] jnoon2: could use some help thinking this out: i have a phoenix channel, connect/join working. in the channel join i start_link a genserver and assign the pid to the socket. the genserver starts a port. so the idea is each user connected to this channel gets a dedicated external process (port). so far so good.
[00:23:58] jnoon2: the idea is the client will constantly push messages, and the server should be in a "work loop" with that external process. as soon as the external process has completed work, it should see what the latest message from the client is and work that one if new. it will not work every message, only the latest.
[00:24:04] jnoon2: now im trying to figure out how/where to start that "work loop", and not sure how to do it. Task, spawn, etc.. any general direction or things i should look into would be helpful
[00:27:44] thurloat: has joined #elixir-lang
[00:36:54] squallster: has joined #elixir-lang
[00:41:21] ankhers: jnoon2: What type of work is being done in the "work loop"? Is any "work" being done on the Elixir side? Or does it start the process, wait for it to end, then do something with that?
[00:43:33] orbyt_: has joined #elixir-lang
[00:43:40] jnoon2: Ankhers: it does something completely outside elixir… tasks .5 - 1 second, and results in a simple string result
[00:45:16] ankhers: When does the "work loop" start? Is it a message from the client? Randomly? Immediate on join?
[00:46:38] jnoon2: i was thinking just start the loop on join, and it checks to see if a message exists from the client, and is different from the last one processed. if so does work, if not just recurses
[00:54:37] ur5us: has joined #elixir-lang
[00:55:21] adkron_: has joined #elixir-lang
[00:57:15] jnoon2: Ankhers: in the join, ive tried spawn_link(__MODULE__, :work_loop, []) with def work_loop() do ; IO.puts("WORK LOOP #{:os.system_time(:millisecond)}"); :timer.sleep(1000); work_loop(); end and that seems to give the expected output. im not sure if its the "right" way, and i still need to figure out how to get to the socket, but maybe its a start
[01:02:00] praveenperera: has joined #elixir-lang
[01:03:26] ankhers: jnoon2: Are these channel topics all unique, or do they share a topic?
[01:03:52] praveenperera: has left #elixir-lang: ()
[01:04:54] jnoon2: Ankhers: "worker:#{project_id}". but the port should be per connection… each connection needed their own.
[01:07:01] ankhers: Okay. I would probably create a new module that can be your gen server. I don't really like using spawn_link directly unless I have to. Then you can pass `self()' as an argument to the spawn_link call so that the new gen server has access to the channel process.
[01:08:33] ankhers: Then this would need a bit of testing, but I think channel processes are just gen servers, so you may be able to use GenServer.cast(pid, {message, result}) from the new genserver where `pid'` is the channel process pid. If that doesn't work, Just use send.
[01:09:53] thurloat: has joined #elixir-lang
[01:10:20] jnoon2: nice. i will try that!
[01:11:13] ankhers: Also, when you do SomeModule.start_link(self()), you can store that pid in your socket.assigns so you can reference it when necessary.
[01:16:03] jnoon2: Ankhers: yes cool im doing that with the port's genserver, so good to know im on the right track
[01:19:09] jnoon2: Ankhers: thanks for your help, going to head home and try to tackle this!
[01:19:34] ankhers: Cool. Good luck! Feel free to ping me if you get stuck with anything.
[01:23:05] greengriminal: has joined #elixir-lang
[01:34:14] tomterl: has joined #elixir-lang
[01:35:50] sevenseacat: has joined #elixir-lang
[01:41:39] harrow: has joined #elixir-lang
[01:48:37] ariedler: has joined #elixir-lang
[01:57:52] jeffweiss: has joined #elixir-lang
[02:07:17] adkron_: has joined #elixir-lang
[02:31:39] jeffweiss: has joined #elixir-lang
[02:53:36] __charly__: has joined #elixir-lang
[03:14:41] d0zingcat: has joined #elixir-lang
[03:14:59] jerme_: has joined #elixir-lang
[03:15:21] adkron_: has joined #elixir-lang
[03:20:45] __charly__: has joined #elixir-lang
[03:56:58] Guest72556: has joined #elixir-lang
[04:02:02] __charly__: has joined #elixir-lang
[04:31:40] adkron_: has joined #elixir-lang
[04:56:55] voltone: has joined #elixir-lang
[05:19:10] jeffweiss: has joined #elixir-lang
[05:23:52] helpa-bot: has joined #elixir-lang
[05:23:53] jnoon2: has joined #elixir-lang
[05:24:08] schakkis: has joined #elixir-lang
[05:24:38] foggyboi: has joined #elixir-lang
[05:25:43] thomasfedb_: has joined #elixir-lang
[05:26:22] helpa-bot: has joined #elixir-lang
[05:27:29] dANO: has joined #elixir-lang
[05:27:43] justinmcp_: has joined #elixir-lang
[05:27:47] Derperpe-: has joined #elixir-lang
[05:28:56] helpa: has joined #elixir-lang
[05:29:06] juba: has joined #elixir-lang
[05:31:42] chazlever: has joined #elixir-lang
[05:32:53] cjk101010: has joined #elixir-lang
[05:32:57] blassin: has joined #elixir-lang
[05:34:03] danolj: has joined #elixir-lang
[05:38:10] jeffweiss: has joined #elixir-lang
[05:40:45] adkron_: has joined #elixir-lang
[05:45:15] mdbm: has joined #elixir-lang
[05:55:00] Sentreen: has joined #elixir-lang
[05:58:00] ndee: has joined #elixir-lang
[05:59:26] mdbm: so I got this piece of code to comment out for a while
[05:59:46] mdbm: the code is on multiple lines
[06:00:02] mdbm: so I try to make it just a string with """ ... """
[06:00:11] mdbm: but in that piece of code I do string interpolation
[06:00:51] mdbm: e.g. "Record for #{user.firstname} was created"
[06:00:57] mdbm: so commenting with """ seems not to work if there is string interpolation in the code
[06:01:01] mdbm: what should I do?
[06:03:16] Nicd-: comment every line with #
[06:03:33] Nicd-: or delete it and later bring it back from git history
[06:03:40] wonko7: has joined #elixir-lang
[06:04:17] sevenseacat: stash it in git and then pop the stash later
[06:04:40] sevenseacat: use an editor macro to select multiple lines and comment them all
[06:04:49] mdbm: will there be real multiline-comment support in the future?
[06:04:55] Nicd-: most likely not
[06:05:27] Nicd-: documentation already works with """ and not many other reasons to comment big blocks
[06:07:34] mdbm: well luckily my IDE seems to be able to comment out multiple lines with # and reverse
[06:08:05] sevenseacat: hate when people check in commented out code
[06:16:29] wonko7: has joined #elixir-lang
[06:17:43] tuacker: has joined #elixir-lang
[06:18:41] sangoma: has joined #elixir-lang
[06:20:54] maqbool: has joined #elixir-lang
[06:21:38] jeffweiss: has joined #elixir-lang
[06:22:22] jeffweiss: has joined #elixir-lang
[06:23:38] DTZUZO: has joined #elixir-lang
[06:41:01] proteusguy: has joined #elixir-lang
[06:43:13] wonko7: has joined #elixir-lang
[06:46:49] ur5us: has joined #elixir-lang
[06:48:37] micmus: has joined #elixir-lang
[06:53:48] adkron_: has joined #elixir-lang
[06:59:55] ur5us: has joined #elixir-lang
[07:03:26] voltone: has joined #elixir-lang
[07:13:44] mdbm: has joined #elixir-lang
[07:17:55] ndee: has joined #elixir-lang
[07:23:38] snapet_: has joined #elixir-lang
[07:33:08] maqbool: has joined #elixir-lang
[07:39:46] mdbm: has joined #elixir-lang
[07:47:22] gvaughn: has joined #elixir-lang
[07:49:04] jmcgnh_: has joined #elixir-lang
[07:53:32] PragTob: has joined #elixir-lang
[07:56:29] adkron_: has joined #elixir-lang
[08:38:15] hypercore: has joined #elixir-lang
[08:42:40] gvaughn: has joined #elixir-lang
[08:46:30] mdbm: So I got the following error: struct field names must be atoms, got: {"user_id", nil}
[08:46:38] mdbm: on the following line:
[08:46:40] mdbm: belongs_to(:user_details, Calendarful.User, foreign_key: "user_id")
[08:46:58] mdbm: but "user_id" is not is not a "field name" ?
[08:47:45] serafeim: mdbm: try :user_id instead of "user_id"
[08:47:58] mdbm: serafeim, yeah that will work, just trying to understand
[08:48:06] serafeim: mdbm: foreign_key: "user_id" is not a correct syntax
[08:48:20] serafeim: hmmm no sorry
[08:48:23] serafeim: it is correct syntax :)
[08:48:47] serafeim: it just doesn't seem to be working for the declaration
[08:49:52] Nicd-: from belongs_to documentation: ":foreign_key - Sets the foreign key field name"
[08:49:58] serafeim: i recommend taking a look at this: https://hexdocs.pm/ecto/Ecto.Schema.html#belongs_to/3
[08:50:03] Nicd-: so "user_id" was indeed a field name in that call
[08:50:19] serafeim: the `foreign_key: "user_id"` probably won't work. you'
[08:50:27] mdbm: Nicd-, why it has to be an atom? just curious
[08:50:44] Nicd-: because Ecto says so :P
[08:50:52] serafeim: the foreign_key: :user_id
[08:51:16] serafeim: also if you leave out the foreign_key declaration it should probably work
[08:51:34] serafeim: because by default it is the name of the association suffixed by `_id`
[08:52:15] mdbm: serafeim, yeah but I don't want it to be the same in this case, that's why I used that option
[08:52:17] mdbm: thanks guys
[08:58:09] mdbm: should I use this option on_delete: :delete_all in my migration for the references?
[08:58:26] Nicd-: it depends on the situation
[08:58:34] Nicd-: so: "use it if you need to use it" :P
[08:58:52] wonko7: has joined #elixir-lang
[08:59:13] mdbm: Nicd-, shouldn't I be consistent and always use it or never? otherwise it is quite unpredictable, like, did I enable this option in this schema? gotta check the source to know
[08:59:32] Nicd-: it depends on the relationship
[09:00:38] Nicd-: if you have a user and a user has private messages for example, you want the messages to be deleted when the user is deleted. but if they have log events, you may not want them to be deleted but preserved instead for regulatory / maintenance reasons
[09:00:48] Nicd-: so it always depends on the relationship of the tables
[09:01:05] mdbm: Nicd-, nice example
[09:01:07] serafeim: Nicd-: i always set such things to PROTECT to avoid thinking about it
[09:01:33] serafeim: Nicd-: *if* for whatever reason i need to delete something i prefer to explicitly delete things than having something deleted without me wanting to
[09:01:43] Nicd-: that's one choice
[09:02:01] serafeim: also i always never delete things from my database. i usually set an `is_active` field to false
[09:02:08] serafeim: or `is_removed` to true.
[09:02:24] Nicd-: I use the DB's cascade (`:delete_all`) to delete all user information from my site in one query
[09:02:41] adkron_: has joined #elixir-lang
[09:04:57] mdbm: serafeim, soft deletes add additional complexity where most of the times they are not needed
[09:06:44] Nicd-: in my case, soft delete would not be legal :D user privacy and all that
[09:07:03] mdbm: yeah, with gdpr now it even makes less sense
[09:08:23] serafeim: ha ha ha ha hayes
[09:08:40] serafeim: gdpr is so funny
[09:15:39] mdbm: I'm checking out the following code:
[09:15:41] mdbm: https://gist.github.com/marinho10/6bf9df674cbfa03fa0262d405bb51975#file-myapp-repo-migrations-addtableuserproject-ex
[09:15:51] mdbm: is the unique index really necessary?
[09:16:13] mdbm: because he defines :project_id and :user_id as being the primary key
[09:16:25] mdbm: then he creates the unique index: unique_index(:user_project, [:user_id, :project_id], ...
[09:16:52] mdbm: and then he additionally he adds two indexes for both fields...
[09:17:32] mdbm: with primary keys, you already got that unique constraint
[09:21:06] serafeim: yes it does not seem necessary
[09:21:22] ur5us: has joined #elixir-lang
[09:21:29] mdbm: serafeim, not sure about the individual indexes as well..
[09:21:43] serafeim: mdbm: the individual indexes are needed for querying
[09:21:59] serafeim: i mean they offer something
[09:22:04] Nicd-: might be useful if you want to get all users with a certain project for example
[09:22:09] notzmv: has joined #elixir-lang
[09:22:11] mdbm: serafeim, yeah but he defined them already as primary keys
[09:22:28] serafeim: mdbm: yes but that's a composite primary key
[09:22:49] Nicd-: it's a combined primary key, it won't help when querying one of the fields
[09:22:50] serafeim: mdbm: also, as a general commend i never use composite primary keys
[09:23:07] serafeim: there's no real reason nowadays
[09:23:46] serafeim: just add a simple id-key instead of complicating your life with composite pks
[09:24:22] jmiven: has joined #elixir-lang
[09:24:58] serafeim: mdbm: the snippet you shown us is an M2M table
[09:25:05] mdbm: serafeim, I always use id-key. but here it's a joint table. The two foreign keys identify a row
[09:25:28] mdbm: serafeim, seems like a valid reason to use a composite in this case
[09:25:30] serafeim: here's how i would define an M2M table: https://dpaste.de/6bDd
[09:26:14] serafeim: and here's the migration for that: https://dpaste.de/yEUm
[09:26:38] serafeim: as you see i'll leave it to ecto to add me the default primary id key
[09:26:57] serafeim: but i'll add the proper indeces for integrity and querying speed
[09:27:46] serafeim: actually this is what django is doing by default when you add an m2m relation so i'd rather follow that practice
[09:27:52] mdbm: serafeim, but you're ecto-generated ID is quite useless
[09:28:26] ur5us: has joined #elixir-lang
[09:29:27] mdbm: serafeim, I don't favor composite keys because in general it means you want to use natural keys, I'm all for artificial/surrogate keys. But the composite key of user_id and permission_id is a combination of two ecto-generated artificial keys. so seems useless to me to use id field
[09:30:15] serafeim: mdbm: it is not useless for me. for example i may want to add a foreign key to that table (users_permissions). then what ?
[09:30:22] serafeim: mdbm: i'll add a composite foreign key ?
[09:31:12] serafeim: mdbm: also what is the syntax in ecto for adding a composite foreign key ? are you sure you know it and it works fine ?
[09:31:13] mdbm: serafeim, so you mean, in that table, the combination of a user and permission might not be unique in the future?
[09:31:32] serafeim: mdbm: no i mean i may have another table that wants to reference that relation
[09:31:41] mdbm: serafeim, dunno why you're talking about composite foreign keys, we talk about composite primary keys here
[09:31:54] mdbm: serafeim, foreign keys are not composite
[09:32:04] serafeim: mdbm: why not ?
[09:32:28] serafeim: mdbm: let's say that you wanted to reference the relation between a user and a group. for whatever reason. how would you do that ?
[09:32:47] mdbm: serafeim, sorry just understood what you mean
[09:33:10] serafeim: wouldn't that lead you to composite foreign keys ? do you see that you open a read to hell ?
[09:33:13] mdbm: serafeim, well thanks, you're right, now I have to remove that composite key
[09:33:15] serafeim: a road to hell
[09:34:11] serafeim: well that's my opinion. other people may want to be pure and normalized and don't want to add an extra PK
[09:36:04] mdbm: serafeim, well I need to reference a joint table, I didn't think about it
[09:36:20] mdbm: it will be more simple in the code as well
[09:36:38] serafeim: mdbm: it should be possible but i wouldn't want to solve that problem :)
[09:42:13] mahmudov: has joined #elixir-lang
[09:44:27] voltone: has joined #elixir-lang
[09:49:53] hypercore: has joined #elixir-lang
[10:14:25] adkron_: has joined #elixir-lang
[10:25:09] wonko7: has joined #elixir-lang
[10:29:43] gvaughn: has joined #elixir-lang
[10:39:47] Benjojo: has joined #elixir-lang
[11:10:00] mdbm: I can't find the preload option for Repo.all/2
[11:10:02] mdbm: https://hexdocs.pm/ecto/Ecto.Repo.html#c:all/2
[11:10:15] mdbm: I can't preload associations when using Repo.all? :-/
[11:13:02] serafeim: mdbm: something like this should work: Repo.all(User) |> Repo.preload(:permissions)
[11:13:17] serafeim: or else you can put the preload keyword to your query
[11:14:46] mdbm: serafeim, why isn't it included as an option to Repo.all/2
[11:15:29] serafeim: mdbm: i'm not sure :)
[11:15:37] serafeim: i think it's a different thing
[11:15:52] serafeim: the Repo.all is similar to Repo.first or Repo.paginate
[11:16:13] serafeim: they take a query and "run it"
[11:17:37] mdbm: serafeim, I guess Repo.all(User) |> Repo.preload(:permissions) will be less performant than loading in the query
[11:17:53] serafeim: mdbm: yes this will take more than 1 queries
[11:18:26] serafeim: mdbm: actually you can try them in the the iex and see how many queries are generated
[11:18:50] serafeim: mdbm: also notice that if you *just* put a preload keyword in your query *it will have the same behavior of generating an extra query*
[11:18:57] serafeim: yes this seems crazy but that's how it works
[11:19:26] serafeim: if you want to avoid the extra query generation you need to add a specific join in your query and then assign they keyword of that join in your preload
[11:20:18] serafeim: read this and you'll see what happens: https://hexdocs.pm/ecto/Ecto.Query.html#preload/3
[11:24:51] mdbm: serafeim, would have been nice if it generated a join
[11:24:59] adkron_: has joined #elixir-lang
[11:25:03] mdbm: why would one prefer two queries anyway
[11:25:15] serafeim: mdbm: not sure :)
[11:28:38] Phylock: has joined #elixir-lang
[11:30:23] benwilson512: serafeim: mdbm it is only faster sometimes
[11:30:38] benwilson512: and there's a trade off between latency and memory
[11:30:48] benwilson512: consider your user / permissions example
[11:31:10] benwilson512: if there are 100 permissions and you use a join in the query, it duplicates the user data 100 times in the returned result rows
[11:31:45] benwilson512: ecto dedups, but that's still 100x duplicated user data that has to go across the wire and be parsed and so forth
[11:35:03] serafeim: it's better to be explicit than implicit
[11:35:37] serafeim: after all if ecto wanted to be implicit it would auto-forward the relations (like django does) instead of having you explicitly declare what you want to preload
[11:40:17] PragTob: has joined #elixir-lang
[11:40:35] voltone: has joined #elixir-lang
[11:43:49] drincruz_: has joined #elixir-lang
[11:43:52] mdbm: is there any difference between
[11:43:54] mdbm: &(&1.language == language)
[11:43:57] mdbm: &(&1.language = language)
[11:44:14] mdbm: well I know the latter assigns as well
[11:44:29] benwilson512: it assigns if you have a variable on the left, which you do not
[11:44:45] benwilson512: https://www.irccloud.com/pastebin/c2qP0UyF/
[11:48:46] serafeim: benwilson512: won't == return true/false also ?
[11:48:55] serafeim: the = won't return true/false
[11:49:51] mdbm: yeah thanks, I see that it willr eturn a MatchError, I forgot about that
[11:50:25] mdbm: so I'm using Enum.find/3
[11:50:28] mdbm: translation = Enum.find(translations, &(&1.language == language))
[11:50:36] mdbm: now what shoudl I do if translation is nil
[11:50:50] mdbm: i.e. no element has been found in the array
[11:51:07] mdbm: in other programming language I would use an if statement and check for nullity
[11:51:12] mdbm: but that's not the elixir way?
[11:52:23] dysfun: you could, but i'd rather use a case
[11:53:34] mdbm: ok I will give case a try thanks
[11:55:45] mdbm: and is it possible to merge a struct into another struct, but skipping all the meta attributes such as __meta__, __struct__, and so on?
[11:56:24] mdbm: I found https://hexdocs.pm/elixir/Map.html#merge/2
[11:56:30] mdbm: I'll see if it skips all the meta
[11:57:45] Nicd-: it would be better to be explicit about it IMO
[11:58:42] hypercore: has joined #elixir-lang
[11:59:16] maqbool: has joined #elixir-lang
[12:00:00] OliverMT: mdbm: run both structs through Map.from_struct
[12:05:33] paxis: has joined #elixir-lang
[12:07:14] paxis: has joined #elixir-lang
[12:09:57] drincruz_: has joined #elixir-lang
[12:17:50] mdbm: OliverMT, Ecto adds __meta__ attribute, that's not filtered out, whatever I'll forget this idea and merge the fields one by one
[12:17:58] gvaughn: has joined #elixir-lang
[12:18:01] mdbm: OliverMT, you know by the way what is this __meta__ attribute for?
[12:19:27] serafeim: mdbm: they are for keeping database related things https://hexdocs.pm/ecto/Ecto.Schema.Metadata.html
[12:20:03] juba: has joined #elixir-lang
[12:20:19] serafeim: mdbm: usually to merge things in an ecto schema you will use changesets
[12:23:39] maqbool: has joined #elixir-lang
[12:24:32] mdbm: serafeim, probably I misunderstood, but I thought changesets was to insert/update to the db
[12:25:02] mdbm: serafeim, in my case I query some entity, and I need to change the structure a little bit
[12:27:33] dimitarvp: has joined #elixir-lang
[12:29:49] sangoma: has joined #elixir-lang
[12:33:50] Benjojo_: has joined #elixir-lang
[12:34:14] adkron_: has joined #elixir-lang
[12:51:54] duane: has joined #elixir-lang
[12:53:59] maqbool: has joined #elixir-lang
[12:58:56] nickjj: i'm reading that you really shouldn't query your db in a custom validator, but what pattern would you use if you want to throw a validation error if a db result isn't returned back from performing a query?
[12:59:34] either|or: has joined #elixir-lang
[12:59:44] nickjj: the use case is i'm looking up eligible discounts and i want to render a legit ecto validation form error of "did not match any active discounts" -- but the only way i'm able to pull this off is by querying the DB inside of the custom validator
[13:00:46] jeffweiss: has joined #elixir-lang
[13:02:37] benwilson512: nickjj: that's subject to race conditions
[13:03:11] benwilson512: broadly there are two approaches, depending on whether you're going to use a foreign key or not
[13:03:22] benwilson512: if you are gonna use a foreign key, use a foreign key constraint, and then that'll just solve itself when you try to insert
[13:03:36] benwilson512: if you aren't using a foreign key, query discounts ahead of time, and pass the available discounts and the changeset into a common function
[13:03:56] benwilson512: this allows you to easily validate multiple things for example without doing N database queries
[13:05:51] nickjj: benwilson512, the implementation looks like this at the moment https://gist.github.com/nickjj/8332607de12a3ae473af11b09175b6b5
[13:07:36] nickjj: this changeset is in relation to returning 0 or more coupons -- think about a user entering a discount code in a form and being either presented with an active discount (eligible) or non-active discount (not eligible)
[13:07:46] nickjj: well, technically 0 or 1 discounts
[13:08:21] nickjj: that's why i wanted the 0 case to be handled inside of the validator, so i can show a form error next to the text field where they entered the code
[13:11:24] nickjj: i guess i'm just missing the link where i can pass the "ahead of time query" into a validator
[13:12:02] ericmj: your validator is a function, so it's simply an extra argument to your function
[13:12:25] nickjj: i could see maybe running the eligible query before the changeset and returning back a normalized list of discount codes like ["foo", "bar", "bar"] but how would i pass that list into validate_inclusion so i can continue providing the user feedback if it fails?
[13:17:07] benwilson512: nickjj: you pass the list of discount codes as an argument into the a changeset function
[13:17:08] nickjj: ericmj, something like this? https://gist.github.com/nickjj/aca8cadd5ed2aa3725e386f875be3ab6 , but a race condition could technically happen here right?
[13:17:25] benwilson512: right, you may want to rename `def changeset` to something more specialized
[13:17:30] ericmj: yes and yes
[13:17:36] benwilson512: like `def apply_discount`
[13:17:44] ericmj: there is no way around the race condition
[13:17:56] benwilson512: and not cast `discount_code` in the normal changeset fun
[13:18:39] nickjj: benwilson512, thanks. in this case that changeset is part of a checkout embedded schema
[13:19:15] nickjj: actually sorry, i meant an apply discount embedded schema
[13:19:39] nickjj: the race condition is interesting tho, i guess i'll have to live with it
[13:21:01] nickjj: thanks, i do think this a bit cleaner in the end, and makes testing potentially easier
[13:21:05] ericmj: if you can set up a database constraints that checks for the same thing you can avoid the race condition
[13:21:16] ericmj: but I can't see if that's possible without seeing the actual code
[13:21:32] nickjj: ericmj, what code are you interested in seeing to determine that?
[13:21:41] ericmj: the query and the schemas
[13:25:02] nickjj: ericmj, these are the related schemas https://gist.github.com/nickjj/f982d94f073462e56b516d01581491b9
[13:25:15] nickjj: and the other gist has the main query being used
[13:26:52] nickjj: so eligibility is really a combination of 2 things, making sure it's available for a specific package (discount_packages table) but also the code itself has a bunch of rules (discounts table) like max redemptions and date based expiration (which i omit from the schema for brevity)
[13:29:11] ericmj: right, it's not possibly to write a constraint for that since you are not changing anything in the database around the discounts
[13:29:44] ericmj: and the race condition should be rare and maybe even fine since I am guessing you are rarely changing discounts?
[13:29:51] nickjj: at the point of determining its eligibility? that's correct , it's just going to be a bunch of where conditions to make sure they are not expired
[13:30:27] nickjj: yeah typically a discount would be created and then not touched, and then soft deleted when it expires
[13:31:34] nickjj: but the race condition could be 1. discount is determined to be eligible , 2. changeset passes but in between 1 and 2 someone uses the last available discount
[13:31:59] nickjj: or the system time pushes it 1 second past the expiration date
[13:35:05] lauromoura: has joined #elixir-lang
[13:35:52] __charly__: has joined #elixir-lang
[13:42:00] gvaughn: has joined #elixir-lang
[13:42:35] gvaughn: has joined #elixir-lang
[13:43:19] mdbm: has joined #elixir-lang
[13:45:48] adkron_: has joined #elixir-lang
[14:00:25] jeffweiss: has joined #elixir-lang
[14:09:12] maqbool: has joined #elixir-lang
[14:12:51] nduro: has joined #elixir-lang
[14:22:59] __charly__: has joined #elixir-lang
[14:23:21] adkron_: has joined #elixir-lang
[14:30:03] greengriminal: has joined #elixir-lang
[14:49:15] wsieroci: has joined #elixir-lang
[15:00:43] mdbm: has joined #elixir-lang
[15:09:31] jeffweiss: has joined #elixir-lang
[15:18:46] pera: has joined #elixir-lang
[15:33:50] tuacker: has joined #elixir-lang
[15:43:10] icecreamcohen: has joined #elixir-lang
[15:48:07] jnoon2: has joined #elixir-lang
[15:48:55] jeffweiss: has joined #elixir-lang
[15:49:52] jeffweiss: has joined #elixir-lang
[15:59:15] drincruz_: has joined #elixir-lang
[16:20:34] mfb2: has joined #elixir-lang
[16:21:03] icecreamcohen: has joined #elixir-lang
[16:26:08] gvaughn_: has joined #elixir-lang
[16:28:23] squallster: has joined #elixir-lang
[16:37:52] d10n-work: has joined #elixir-lang
[16:40:54] wsieroci: has joined #elixir-lang
[16:45:52] thurloat: has joined #elixir-lang
[16:47:45] cschneid: has joined #elixir-lang
[16:49:41] m17: has joined #elixir-lang
[16:50:00] foggyboi: has joined #elixir-lang
[16:50:38] Disorganized: has joined #elixir-lang
[16:55:16] paulo1993: has joined #elixir-lang
[16:56:02] sangoma: has joined #elixir-lang
[16:58:00] mahmudov: has joined #elixir-lang
[16:59:06] drincruz_: has joined #elixir-lang
[17:00:21] proteusguy: has joined #elixir-lang
[17:06:59] paulo1993: CAn I ask question about some problems that i'm having right now with ecto here? If this is the wrong place, I'm sorry.
[17:11:43] gamache: paulo1993: I'm not personally much of an Ecto jockey, but yeah ask away!
[17:21:11] sangoma: has joined #elixir-lang
[17:31:25] icecreamcohen: has joined #elixir-lang
[17:34:11] drrty: has joined #elixir-lang
[17:39:13] iFire: has joined #elixir-lang
[17:44:01] Disorganized: has joined #elixir-lang
[17:45:35] mdbm: if I have a structure, and the name of a key in two variables, how can I access the value for that key in the structure?
[17:50:57] jeffro: has joined #elixir-lang
[17:53:02] ankhers: Map.get(my_struct, :key). Replace :key with your variable.
[17:53:11] ankhers: Structs are just named maps.
[18:01:56] mdbm: Ankhers, thanks, works:)
[18:03:09] warmwaffles: has joined #elixir-lang
[18:04:34] jeffro: has joined #elixir-lang
[18:07:27] wsieroci: has joined #elixir-lang
[18:08:47] paulo1993: Let's think that i have the schema card ```defmodule Nightcrawler.ES.Card do use Ecto.Schema import Ecto.Changeset schema "card" do field :number, :integer field :name, :integercard end @doc false def changeset(card, attrs) do card = card_status |> cast(attrs, [:number, :name]) |> validate_required([:number, :name]) |> apply_action(card, :insert) |> IO.inspect end end``` And people
[18:08:59] paulo1993: First time in irc
[18:09:11] foggyboi: has joined #elixir-lang
[18:09:17] gamache: no problem -- we usually use something like Pastebin for code samples
[18:12:13] paulo1993: https://codeshare.io/5QL7QR
[18:12:23] paulo1993: In this code I have a card schema and a person one
[18:12:34] paulo1993: Person embbeds many schemas
[18:13:05] paulo1993: Then, in the person's changeset i call cast_embed buuuut
[18:13:16] paulo1993: It turns out to return the errror commented in the code
[18:13:30] paulo1993: (people and card are only examples in this case)
[18:15:37] gamache: paulo1993: I think the problem is that changeset/1 is supposed to return just the changeset, but the result of apply_action/2 is {:ok, changeset} and you're using that as the return value
[18:15:38] ankhers: What is your reason for using apply_action/2? Ecto generally just does the right thing there.
[18:16:04] gamache: ^^ that is also a valid question, and exposes my weak knowledge of Ecto :)
[18:16:51] greengriminal: has joined #elixir-lang
[18:18:16] foggyboi: has joined #elixir-lang
[18:23:01] paulo1993: This is my reason: (CompileError) lib/nightcrawler/es/slot_status.ex:18: undefined function apply_action/1
[18:23:23] mdbm: I have seen something like this in Ecto: select: map(q, [:id, :statement])
[18:23:27] paulo1993: I understand know the question
[18:23:29] mdbm: from where does this map() come from?
[18:23:40] paulo1993: I have very little knolegment about this
[18:23:52] paulo1993: Another thing. My english is not that good.
[18:24:47] paulo1993: My reason to use the apply_change is to generate the struct
[18:25:42] paulo1993: %person{name:"aaaa", cards: [%Card{blablabla}]}
[18:28:28] jeffro: has joined #elixir-lang
[18:30:57] paulo1993: @gamache, i corrected, and the message changed to key :action not found in: %Nightcrawler.ES.Card{...}
[18:32:04] gamache: I'm afraid I can't help much more, then -- I'm not great at Ecto
[18:32:38] paulo1993: Thanks, anyway
[18:45:10] laut: does anyone know of some books that are currently being written (or will come out in new versions) that involve Ecto?
[18:57:40] ankhers: laut: https://pragprog.com/book/wmecto/programming-ecto I have not read it myself.
[18:58:05] ankhers: paulo1993: I think if you remove the apply_action/2 call, things should work for you.
[18:58:54] Disorganized: has joined #elixir-lang
[19:00:27] foggyboi: has joined #elixir-lang
[19:07:43] laut: Ankhers: thank you. I am hoping that books with Ecto examples using timestamps will use the :utc_datetime type
[19:14:38] Czen: has joined #elixir-lang
[19:18:20] greengriminal: has joined #elixir-lang
[19:19:11] gvaughn: has joined #elixir-lang
[19:19:22] paulo1993: @ankhers, I tried. Then, it will return the chanset. That's not what I want
[19:19:53] ankhers: paulo1993: Then what is it you are trying to accomplish?
[19:21:16] paulo1993: I want to create a struct like this: %person{name:"aaaa", cards: [%Card{blablabla}]}
[19:21:28] Czen: has joined #elixir-lang
[19:21:33] ankhers: apply_action/2 does not actually do the insert/update/etc. You will need to actually call `MyApp.Repo.insert(changeset)
[19:23:43] gde33: has joined #elixir-lang
[19:24:04] ankhers: paulo1993: When you say "create a struct", presumably you mean you also want it in the database?
[19:30:46] adkron_: has joined #elixir-lang
[19:33:23] paulo1993: I'm sorry. I'm using only ecto. I only want to control and validate structs
[19:33:33] paulo1993: I'm not using ecto-sql
[19:38:21] ankhers: Oh okay. Try removing the call to apply_action in the embedded Card.changeset function.
[19:39:23] ankhers: I believe you will still want to return a changeset from that function. Then when you use the apply_action/2 in the People.changeset function, it should do the right thing.
[19:52:03] nickjj: does anyone know how to select specific fields from a joined table with ecto? hit a brick wall and i can't find a solution googling -- here's the query + current results + what i'm trying to get back https://gist.github.com/nickjj/9a46edc4c4d5c08b5769eb139a2feaab
[19:52:22] nickjj: i tried a whole bunch of different combinations of using select in the query, but nothing worked
[19:54:42] nickjj: the closest i can come up with is [{"HELLO"}] as the output which isn't quite ["HELLO"]
[19:56:10] foggyboi: nickjj: just eyeballing quickly but did you try `select: [d.code]`
[19:56:37] nickjj: foggyboi, using select: d.code , ended up working as long as i removed the preloads
[19:56:59] nickjj: a few examples i saw had things like , select: {d.code} , i thought the {} was necessary
[19:57:08] foggyboi: yeah nah that puts it in the tuple
[19:57:31] jeffro: has joined #elixir-lang
[19:59:22] nickjj: foggyboi, do you happen to know if it's possible to situationally do that select/preload based on a condition being true or not?
[19:59:34] Cthalupa: has joined #elixir-lang
[19:59:36] nickjj: for example, to avoid doing this: https://gist.github.com/nickjj/2930786c8b0a90852b8ee2be08c2dccc
[20:00:08] nickjj: i haven't quite figured out how to connect the dots on reusing queries
[20:00:25] warmwaffles: nickjj, I'd just pass that query into a pattern matched method that would add the preload
[20:00:32] foggyboi: oh I see, let me find somewhere where I do it
[20:01:52] cschneid_: has joined #elixir-lang
[20:01:58] nickjj: warmwaffles, in this case it's more than just preloading or not -- it's either selecting just the codes and not preloading or selecting everything and preloading
[20:02:02] Disorganized: has joined #elixir-lang
[20:06:42] warmwaffles: left you a comment https://gist.github.com/nickjj/2930786c8b0a90852b8ee2be08c2dccc
[20:06:47] pera: has joined #elixir-lang
[20:07:04] warmwaffles: wouldn't work
[20:07:12] warmwaffles: but it's what I was more or less referring to
[20:08:35] nickjj: would that same strategy apply for selecting just the code or not too?
[20:08:51] nickjj: basically another function to replace the the `select: d.code,` line in your comment
[20:09:22] warmwaffles: I prefer to compose the queries as best as I can and hide that complexity within the schema holding module itself
[20:11:08] nickjj: yeah that's what i would like to do eventually, still figuring out how to compose them nicely
[20:11:52] greengriminal: has joined #elixir-lang
[20:13:29] greengriminal: has joined #elixir-lang
[20:16:49] nickjj: but your comment really helped to see how maybe i can extract some of that into reusable queries (didn't get a solution for my question, but at least was able to refactor a few things) -- thanks!
[20:17:42] warmwaffles: not a problem
[20:18:01] warmwaffles: it was a moment of clarity for me as well when someone showed me a similar strategy
[20:22:53] gvaughn: has joined #elixir-lang
[20:23:00] nickjj: warmwaffles, something like this is working so far , would you say this is idiomatic usage of query composing? https://gist.github.com/nickjj/1883599c9e598ffe24feb97542971973
[20:23:40] nickjj: my naming conventions aren't the best yet, but it is functional in the sense it produces 1 query with the correct results based on what L35's arguments are
[20:27:40] jeffweiss: has joined #elixir-lang
[20:28:30] jeffweiss: has joined #elixir-lang
[20:29:46] warmwaffles: naming things is hard... hardest one was naming my daughter
[20:30:05] warmwaffles: people generally frown at you when you call your child c1 or spawn
[20:33:24] nickjj: do you happen to have an example of how to compose a query where you want to access the joined field, without having to explicitly do the join again?
[20:34:29] warmwaffles: I think you are going to need to do the join again because you wont have access to it outside of the scope... Although I am curious to see if ecto's sql knows what to do and doesn't do another inner join
[20:35:01] jeffro: has joined #elixir-lang
[20:36:15] nickjj: with the gist, if i look at the raw sql, it's doing an INNER JOIN 3 times
[20:36:42] nickjj: i left a comment with the query
[20:37:27] nickjj: now, i did see another example online from 2015 where someone did: query |> where([c], c.votes > 10)
[20:37:51] warmwaffles: one of the examples I am seeing here is `from [p, ..., c] in posts_with_comments, select: {p.title, c.body}`
[20:37:55] nickjj: and prior to using that query, they did the join in another query
[20:38:03] warmwaffles: but that won't help here :/
[20:38:05] nickjj: check the bottom of this post https://blog.drewolson.org/composable-queries-ecto
[20:38:47] nickjj: this is doing exactly what i'm trying to do with a join -- but when i try it, elixir won't even compile with this error: unbound variable `d` in query. If you are attempting to interpolate a value, use ^var
[20:39:04] warmwaffles: look at the `def popular`
[20:39:04] nickjj: that was with doing: where(query, [d], d.code == ^String.upcase(code))
[20:39:13] nickjj: yes, that is what i tried to emulate on my end
[20:39:50] nickjj: in his final example he first joins the post with the comment and then does popular on it
[20:39:51] warmwaffles: you don't have access to d because in your original `from` if you look at `for_post`
[20:40:11] warmwaffles: you'll see `from c in query` which is where it gets the `[c]` in popular, I believe
[20:41:33] warmwaffles: nickjj, is it that bad to just preload it always?
[20:42:12] nickjj: yes, because if i try to preload it when doing the select, then ecto throws an error
[20:46:30] jeffro: has joined #elixir-lang
[20:47:52] nickjj: warmwaffles, i got it -- it only produces 1 inner join now, and it's still composable
[20:48:20] nickjj: the syntax was this: from([_q, d] in query, select: d.code)
[20:49:14] warmwaffles: will use this
[21:06:47] icecreamcohen: has joined #elixir-lang
[21:14:17] Disorganized: has joined #elixir-lang
[21:20:06] Sgeo: has joined #elixir-lang
[21:21:37] aalmazan: has joined #elixir-lang
[21:23:04] Disorganized: has joined #elixir-lang
[21:42:15] ur5us: has joined #elixir-lang
[21:45:23] haste: has joined #elixir-lang
[21:48:30] __charly__: has joined #elixir-lang
[22:28:48] hypercore: has joined #elixir-lang
[22:30:04] jeffro: has joined #elixir-lang
[22:34:15] greengriminal: has joined #elixir-lang
[22:43:18] jnoon2: Ankhers: your suggestion yesterday worked well. i think i have it all squared away and even have a better understanding of genservers now. pretty cool, thanks again!
[22:44:51] Disorganized: has joined #elixir-lang
[23:04:21] Disorganized: has joined #elixir-lang
[23:19:37] cschneid_: has joined #elixir-lang
[23:22:20] __charly__: has joined #elixir-lang
[23:24:30] Disorganized: has joined #elixir-lang
[23:42:14] arpunk: has joined #elixir-lang
[23:44:10] cschneid_: has joined #elixir-lang
[23:54:56] cschneid_: has joined #elixir-lang