#elixir-lang - 27 May 2019
« Back 1 day Forward 1 day »
[09:21:45] rawtaz: is anyone aware of an AFTN parser for Elixir (or Erlang, i suppose)? https://en.wikipedia.org/wiki/Aeronautical_Fixed_Telecommunication_Network#AFTN_Message_Format
[09:23:32] hypercore: guys is it worht using a managed database if i think my website will be popular?
[09:26:27] hypercore: not sure what other ways of accessing the data exist other than what normally happens
[09:41:36] dch: hypercore: for $50/month you can get 8x the RAM, 8 actual cores (not hyperthread garbage), on real tin. https://www.packet.com/cloud/servers/t1-small/ I run a few elixir apps on these and its absolutely excellent. I'd not be comfortable about running a busy DB on a 1GB/1vCPU instance, but then it does depend on what you mean by "popular".
[09:42:33] dch: I'm sure whatever cloud provider you're using can allow you to upgrade the system easily if need be. If you put a load balancer in front right from the beginning, you can move to a bigger instance without downtime if needed.
[09:43:39] dch: Nicd-: nope, I guess I don't ever think a managed DB is worth it for a serious app. Each to their own?
[09:46:34] dch: the restrictions that DO have look pretty onerous https://www.digitalocean.com/docs/databases/overview
[09:48:32] koollman: hypercore: don't worry until it is likely to become a problem. And maybe have a plan for that
[09:53:48] koollman: hypercore: don't pay for expensive stuff too early if you can avoid it, but have a plan for 'sudden success' ready. (which can be "I have backups that I can restore on a much more expensive platform". until you need that plan, it is mostly free :) )
[11:05:39] serafeim: another question. I am using the following query: Repo.all(Withholding) |> Repo.preload([:authority]) to preload some the authority foreign key... now, authority has *another* foreign key (i.e authority_kind). how can I also load this in my query ?
[11:06:18] serafeim: is this possible using this syntax or i'll need to fall back to from Withholding and doing a left join ?
[13:14:09] serafeim: I am using the following query: `Repo.all(Withholding) |> Repo.preload([:authority])` to preload some the authority foreign key... now, authority has *another* foreign key (i.e authority_kind). how can I also load this in my query ? is this possible using this pipe syntax or i'll need to fall back to `from Withholding` and doing a left join ?
[13:22:14] serafeim: gazler: ha ha something like this *but* the :other_thing is a foreign key of :authority !
[16:39:26] nickjj: let's say you had "discounts" and "packages" , and a "discount_packages" join table and then you used has_many throughs to wire it all up
[16:40:07] nickjj: and when creating discounts, you can pick 0 or more packages to apply it to -- this is really the only time you would ever write to the discount_packages join table
[16:40:57] nickjj: so what i did was in the discount_packages changeset, i made the package_id optional and also set a FK constraint on it -- so far so good, this is working
[16:41:47] nickjj: but the problem is when i want to add a discount to apply to all packages, i don't want to insert 10 records for 10 packages, instead i wanted to set null to the package_id -- but when i try to do this with the above changeset, ecto says a null package_id is invalid
[16:42:33] nickjj: and i just skip adding the discount_packages to the discount changeset then nothing gets written to the discount_packages table (but that doesn't work for my use case since it tracks other meta data that i need)
[17:10:18] jnoon: nickjj: so i understand the thinking: so discount_packages has fields discount_id, package_id. and a discount_packages row with a null package_id signifies it belongs to every package?
[17:10:53] nickjj: jnoon, correct. i'm open for suggestions on how to better model that, but that is the current implementation
[17:12:57] jnoon: nickjj: i would rethink that first (strongly IMO). that is creating more complicated logic for determining which discounts are associated with a package and more application-logic to do it correctly
[17:14:33] nickjj: a discount can be applied to 1 or more packages , but i really wanted to avoid having some application logic that says "if 0 packages were selected, then go ahead and create 100 discount_packages rows which is 1 for each package of every course)
[17:15:54] jnoon: nickjj: lets say though you keep that.. list_discounts(package) looks like discounts … where dp.package_id is null or dp_package_id = package.id
[17:18:38] jnoon: nickjj: creating the discount is just create_discount(attrs) then create_discount_package(attrs_with_nil_package_id). maybe its not as bad as i thought. usually i try to avoid things you have to "know" to get the right result in the database and keep it fully relational, but this might be a case
[17:18:40] nickjj: but more specifically on how i plan to use discounts, it would be "on course (package) checkout page, if discount code is present, lookup code from discounts and then see if it's available to all packages or this specific package"
[17:20:00] nickjj: the problem i'm trying to solve is to make sure a discount_id is only ever listed once in discount_packages if package_id happens to be null
[17:21:21] nickjj: because you could totally have a JNOON25 discount that applies to package A and B from course 1 , and also have a JNOON25 discount that applies to package A from course 2 -- but you cannot have a JNOON25 discount that applies to all packages twice (that doesn't make sense)
[17:23:47] jnoon: ah, so discount_id: 1, package_id: null and discount_id: 1, package_id: 2 should not be allowed in your case, but discount_id: 1, package_id: 1 and discount_id: 1, package_id: 2 should?
[17:26:40] nickjj: the unique_index will prevent the third example from happening (reload if you don't see the 3rd example)
[17:27:35] nickjj: i think i may have solved it, but i haven't gotten to checking it yet with changeset validations , but this correctly blocks it at the db level:
[17:27:44] nickjj: execute("CREATE UNIQUE INDEX discount_packages_discount_id_package_id_allow_null_index ON discount_packages (discount_id, coalesce(package_id, -1));"
[17:28:05] jnoon: got it, ya looking at the postgresql docs and see that about nulls… i bet there is a way, checking!
[17:28:27] nickjj: with that added, the DB will properly block the 1 NULL combo from appearing more than once, while properly allowing/disallowing the other examples
[17:29:12] nickjj: the -1 seems crucial, i tried NULL and "" for those values but nothing else worked -- but this stuff is a bit above my paygrade, just googling basically and found that example
[17:31:31] jnoon: well the index (discount_id, coalesce(package_id, -1)) discount_id: 1, package_id: 1 will be (1,1) and discount_id: 1, package_id: null will be (1,-1). its just forcing a value so it can make a proper index for each row. coalesce is like foo || -1
[17:32:39] jnoon: so if package_id is an integer column, then -1 makes sense. if you were using uuids for primary keys then you would have to change it… just depends on the column type
[17:37:27] nickjj: thanks for the clarification on things too, helps a lot to get a 2nd opinion / back and forth on these things
[17:38:01] jnoon: sweet! ya ecto is pretty cool. im pretty new to it and converting some node and ruby stuff and did something with ecto that was really elegant in comparison to what it was in the other codebases. took a while to wrap my head around it and get it right, but its like once you get it right, its just rock solid and done!
[17:39:34] nickjj: yeah, still getting used to it myself, but i'm feeling the same way, once things start to semi-click, it's so clean
[20:35:40] nickjj: is there anything in ecto that allows you to define a bunch of validation rules for many different attributes, but skip doing all of those checks if the attribute being validated isn't cast?
[20:51:27] nickjj: for clarity, this is what i'm trying to do https://gist.github.com/nickjj/98d4dcfe60656594c5f47224cf41e168
[21:04:46] micmus: nickjj: this should already work for everything other than validate_required - all normal validations run only if the value is changed (so it was casted). To fix the required validation you can take the set intersection of the default required fields and allowed fields
[21:06:12] nickjj: micmus, i tried moving the required validations out of the allowed changeset just to see what happens, but some other validations still run that shouldn't
[21:06:37] nickjj: i have an update_change in there that tries to get applied to a field that's not cast
[21:07:45] nickjj: also what if you don't want all allowed attributes to be required? i'm not sure how that could be automated with a set intersection
[21:11:08] micmus: `MapSet.intersection(MapSet.new([:email, :username, :hex_color]), MapSet.new([:email]))` => `MapSet.new([:email])` it only retains elements that are in both sets. But yeah, extracting it out is a good solution too. And probably simpler to understand
[21:15:16] nickjj: in other words, doing this should be fine in any case? https://gist.github.com/nickjj/4074fc1021e17741a22020ba29abd996
[21:15:35] nickjj: basically do the generic changeset, and then always put my changeset specific validations after it?
[21:25:40] nickjj: also wow, thanks for the tip on the mapset, it works as long as you run MapSet.to_list/1 on it to pass to the required validation