jhass changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Crystal 0.35.1 | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
<repo> Blacksmoke16: is it possible to serialize collections lazily with athena-serializer?
<repo> as in: not by turning them into an array
<FromGitter> <Blacksmoke16> hm, how would that work?
<repo> well with JSON::Builder it's easy
<repo> you open an array block and then call to_json(builder) on the elements
<FromGitter> <Blacksmoke16> right but thats not lazy and still makes it an array no?
<repo> sure that's lazy
<repo> you never have to load the entire collection into memory
<repo> and yeah it creates a json array, that's my goal
<repo> i meant: not by calling .to_a on the collection
<FromGitter> <Blacksmoke16> got some example code? because you shouldnt have to do that regardless
<repo> maybe i should be more specific: i want to serialize the result of .all from a granite model
<repo> i tried doing that but just got "null" as a result
<repo> with .all.to_a i get the correct result, but it's not lazy
<FromGitter> <Blacksmoke16> https://athenaframework.org/Routing/StreamedResponse/#Athena::Routing::StreamedResponse.new(status,headers,&) is prob what you want
<repo> eventually yes, but currently i'm just printing something to stdout
<FromGitter> <Blacksmoke16> i think you're just missing an include somewhere, the serializer returns `nil` when it can serialize something
<FromGitter> <Blacksmoke16> same concept, just replace `io` with` STDOUT`
<repo> yeah
<FromGitter> <Blacksmoke16> when it cant*
<FromGitter> <Blacksmoke16> ```class Granite::Base ⏎ include ASR::Model ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=600627ccd8bdab473944f5ca]
<FromGitter> <Blacksmoke16> make sure you have this
<FromGitter> <Blacksmoke16> seems fine, also ensure you have `include ASR::Serializable` in your user model
<repo> i have
<repo> and it works with to_a
<repo> but not without it
<FromGitter> <Blacksmoke16> hmm
<repo> ah!
<repo> .all.each works too
<repo> that should be lazy
<FromGitter> <Blacksmoke16> feel like something is going on
<repo> Blacksmoke16: there's no `pretty` option, right?
<FromGitter> <Blacksmoke16> neg
<repo> kk
<repo> mh i guess .to_a wouldn't make a difference
<repo> because loader just returns an array anyway
<repo> too bad. would be nice if it'd be an iterator
<FromGitter> <Blacksmoke16> alright i was able to reproduce
<FromGitter> <Blacksmoke16> ogh yea this is kinda a pain
<FromGitter> <Blacksmoke16> main issue its trying to serializer the collection, not the actual collection
<repo> yeah
<repo> i don't see it as an athena issue though
<repo> adding .each is fine
<repo> if someday collection will be iterable then that'll be cooler, but for now i'll just have to live with it :)
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/a9x0
<FromGitter> <Blacksmoke16> this is also unfortunate
<FromGitter> <Blacksmoke16> think the more specific overload is being added to the end, which never gets considered since the `_` overload matches everything
<FromGitter> <Blacksmoke16> prob should just get rid of that
<FromGitter> <Blacksmoke16> this would prob be handled via the orm component but 😬
<FromGitter> <Blacksmoke16> if you're not using any serializer features could prob get away with just using json serializable, which would work in this case as there is an explicit method call, versus being based on overloads
<FromGitter> <Blacksmoke16> or maybe a better solution would be some method that specific types could overload that by default returns self
aquijoule_ has joined #crystal-lang
richbridger has quit [Ping timeout: 256 seconds]
Xeago has quit [Ping timeout: 240 seconds]
alexherbo2 has quit [Ping timeout: 260 seconds]
deavmi_ has quit [Read error: Connection reset by peer]
yxhuvud has quit [Quit: No Ping reply in 180 seconds.]
yxhuvud has joined #crystal-lang
<FromGitter> <HertzDevil> it happens because `SomeClass` is defined after an overload references it
<FromGitter> <HertzDevil> some day i should translate restrictions.cr to plain english and put it on the repo's wiki or something
f1refly has joined #crystal-lang
f1reflyylmao has quit [Ping timeout: 264 seconds]
avane has quit [Quit: ZNC - https://znc.in]
avane has joined #crystal-lang
deavmi has joined #crystal-lang
Xeago has joined #crystal-lang
<FromGitter> <mattrberry> I would love for someone to tell me that *I'm* being a dummy here: https://carc.in/#/r/a9ym
<FromGitter> <mattrberry> Any idea why this doesn't work?
<FromGitter> <mattrberry> I can do `Regex.new`, but I feel like there's something else going wrong here
<FromGitter> <mattrberry> Seems like it doesn't like the `/` character after the `then`
<FromGitter> <mattrberry> Putting the regex on the next line without the `then` fixes, it, so that has to be it
<FromGitter> <mattrberry> Wrapping the regex in parens works for now :shrug: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=6006867aa2354e44ac931110]
_ht has joined #crystal-lang
<FromGitter> <naqvis> my guess is that as both `then` and `/` are macros, so mixing them is causing the parsing error
<FromGitter> <naqvis> you could either go with `(` as you already did or go with `begin ... end`
<FromGitter> <naqvis> btw, this should also work ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=6006897bcf8b8277343d717d]
Xeago_ has joined #crystal-lang
aquijoule__ has joined #crystal-lang
<FromGitter> <naqvis> looking at the pattern of regex, i believe you can write your regex method as below ⏎ ⏎ ``` def regex : Regex ⏎ /#{self.to_s}_V\d{3}/ ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=60068a67410c2214400b26d2]
Xeago has quit [Ping timeout: 256 seconds]
Xeago_ is now known as Xeago
aquijoule_ has quit [Ping timeout: 256 seconds]
<FromGitter> <mattrberry> Haha fair, don't even need the case statement :p Thanks!
daemonwrangler has joined #crystal-lang
_whitelogger has joined #crystal-lang
<FromGitter> <asterite> I think it's a bug. I'll fix it. It probably also works if you use a newline instead of then
<FromGitter> <Daniel-Worrall> I have a weird language feature I'd be interested to see. The ability to have the same method do different things based on whether what is calling it uses the value it returns. For example, recently we were talking about having an array method that mutates the array and returns the removed elements as an array. The user wanted to be able to use this without allocating that array that returns. If the
<FromGitter> ... compiler was aware of whether return values are desired, this array could go unallocated, and it'd be more performant at the cost of bin size/compile time/compiler complexity
<FromGitter> <Daniel-Worrall> The way I imagine it in my head is either with a macro flag that is true whether or not the return value is used, or a way to define the same method (+sig) with a different return value (Maybe nil?) and the compiler be able to call the right one
<FromGitter> <Daniel-Worrall> oops, accidently pasted a screenshot there. Nice keyboard shortcut alt+ins probably :^)
<FromGitter> <Daniel-Worrall> As I understand it the language only compiles/processes the methods that are called, so the compiler should be aware of where the call points are and be able to use that to determine which to call or not
<FromGitter> <Daniel-Worrall> and I don't think I've ever seen this language feature elsewhere but please do tell me if you've seen this kind of thing before
<FromGitter> <erdnaxeli:cervoi.se> that could be a nice feature
alexherbo2 has joined #crystal-lang
<FromGitter> <naqvis> I would argue against such magical features as that makes things much hard to reason about. Its always good to be explicit then having things happening magically/silently. So far stdlib comes with bang(!) methods to tell that in-place mutation will happen (that's being explicit). ⏎ ⏎ There are languages which enforces the use of method return value (if explicitly stated in method signature) and ignoring
<FromGitter> ... that value is an error, but haven't seen any which changes the method behavior on using/ignoring its return value.
<FromGitter> <Daniel-Worrall> Though it does seem like magic, I feel like it'd be the type of magic only the stdlib or very performant libs would be interested in. You get the optimisations without having to think about it. It could be introduced in the stdlib as a parameter instead of course. One thing that would concern me is ensuring that you get the same method behaviour for both cases
<FromGitter> <HertzDevil> "very performant" code would simply not use the stdlib
<FromGitter> <HertzDevil> 😂
<FromGitter> <HertzDevil> happens to c++ all the time
<repo> damn i love option parser <3 subcommands makes it really versatile
<repo> also lazy block defaults for getters <3 very nice
<FromGitter> <HertzDevil> til `T <= U` and `U <= T` do not imply `T == U` if they are types
hightower2 has joined #crystal-lang
<FromGitter> <HertzDevil> and because of this, unions aren't even commutative
<FromGitter> <asterite> For example?
<FromGitter> <HertzDevil> https://carc.in/#/r/aa1b
<FromGitter> <HertzDevil> related question
<FromGitter> <HertzDevil> if we decide to remove `NamedTuple` what would double splats become?
<FromGitter> <HertzDevil> keyword lists?
<FromGitter> <HertzDevil> or `Tuple(Tuple(Symbol, T), ...)`?
tankf33der has joined #crystal-lang
<tankf33der> o/
_ht has quit [*.net *.split]
fifr has quit [*.net *.split]
badeball has quit [*.net *.split]
holst has quit [*.net *.split]
jrayhawk has quit [*.net *.split]
jrayhawk has joined #crystal-lang
badeball has joined #crystal-lang
holst has joined #crystal-lang
_ht has joined #crystal-lang
fifr has joined #crystal-lang
postmodern has quit [Quit: Leaving]
<repo> Blacksmoke16: sorry, I must be asking this for the fifth time, but how can i create a ParamConverter which takes a model class as a configuration argument and deserializes it from a json body?
<repo> i tried setting configuration model : ASR::Serializable.class but it doesn't seem to recognize my model as such
<repo> `Error: instance variable '@model' of Bucket::Converters::Record::Configuration must be Athena::Serializer::Serializable:Module, not Bucket::Models::Token.class`
Nekka has joined #crystal-lang
<FromGitter> <Blacksmoke16> `model : ASR::Serializable.class,` should be like the parent abstract class of whats possible for it to handle
<FromGitter> <Blacksmoke16> like `Bucket::Models::Token.class`
<repo> yeah i tried defining a base model abstract class, have that inherit Granite::Base and include ASR::Serializable but then i got some error about @validations already been set or something. lemme check
<FromGitter> <Blacksmoke16> oh well if this is a db model you'd make it `Granite::Base.class`
<repo> yeah i did that too, but then i get an error that no overload matches...
<FromGitter> <Blacksmoke16> yea granite doesnt support inheriting models :/
<repo> one sec
<FromGitter> <Blacksmoke16> did you add ⏎ ⏎ ```class Granite::Base ⏎ include ASR::Model ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=6006e167ac653a0802cadae8]
<repo> probably... at some point? i've been trying for like an hour. all sorts of combinations :D
<repo> but let me try again
<repo> mmh
<repo> Error: no overload matches 'Athena::Serializer::Serializer#deserialize' with types Granite::Base+.class, Symbol, Athena::Serializer::SerializationContext
<repo> oh
<repo> oooh
<repo> ah no
<repo> that _should_ work
<repo> that's weird
<repo> i've done exactly that
<FromGitter> <Blacksmoke16> and you're sure you did `include ASR::Model` in the base granite type?
<FromGitter> <Blacksmoke16> note it says `Model` not `Serializable`
<FromGitter> <Blacksmoke16> hmm
<repo> some load order issue maybe?
<FromGitter> <Blacksmoke16> possibly?
<FromGitter> <Blacksmoke16> ill see if i can reproduce with this paste
<FromGitter> <asterite> HertzDevil: yes, the problems with T <= U and U <= T seem to always be related to the merge we do of tuples or named tuples. I'd like to remove that rule but I think by now it's too late
<FromGitter> <HertzDevil> oh it's not a problem for tuples, only named tuples because the keys are ordered for `==` but unordered for `<=`
<FromGitter> <asterite> HertzDevil: double splats would still be NamedTuple, but maybe you can't freely do `{a: 1, b: 2}`. That said, someone can do `def named_tuple(**args); args; end` so I guess there's no way to remove that. I just wish people would use more `record` and other types
<FromGitter> <HertzDevil> key order also decides the named tuple's internal memory representation...?
<FromGitter> <HertzDevil> https://carc.in/#/r/aa1j
<FromGitter> <HertzDevil> imo named tuple keys should be unordered; if it's strictly for double splats i can't imagine a scenario where key order is important
<FromGitter> <HertzDevil> either that, or always alphabetically ordered, as the compiler sometimes does that internally
<repo> agreed
<FromGitter> <HertzDevil> i mentioned keyword lists because that's what elixir uses and not only are named args ordered they can also have duplicate keys
<FromGitter> <HertzDevil> maybe it's simply an erlang/beam limitation i don't know
<FromGitter> <asterite> @HertzDevil yes, key order gives different named tuple types
<FromGitter> <asterite> but when you do a union of two named tuples with the same keys, regardless of order, the compiler will not create a union but instead create a named tuple where each key is the union of the keys... I can't remember which order wins, but it's always the same
<FromGitter> <asterite> I think in Elixir keyword lists are just lists of tuples, so duplicates are allowed
<FromGitter> <HertzDevil> the first one
<FromGitter> <HertzDevil> yeah
<FromGitter> <HertzDevil> what's the reason for key order
<FromGitter> <HertzDevil> to match `Hash`, or to use them in libs before lib structs were a thing?
<FromGitter> <jrei:matrix.org> maybe to match Ruby
<FromGitter> <Blacksmoke16> raz: i was able to reproduce
<repo> yay!
<repo> guessing you mean me
<FromGitter> <asterite> You mean key order for named tuple?
<FromGitter> <Blacksmoke16> oops, yea
<FromGitter> <Blacksmoke16> i remember it started with an `r` and guessed wrong
<repo> no harm done :D
<FromGitter> <Blacksmoke16> but wasnt able to reproduce with example from the cookbook
<repo> hm that's interesting
<repo> any guesses what might be going on?
<FromGitter> <Blacksmoke16> lmao
<FromGitter> <Blacksmoke16> pebkac :D
<repo> ? :D
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=6006ea022cb18a437c2a7421]
<FromGitter> <Blacksmoke16> you're passing serialization context to deserialization action
<FromGitter> <Blacksmoke16> thats what is causing the no overload matches error
<FromGitter> <Blacksmoke16> not related to the model
<repo> oh for fuck's sake :D
<repo> sorry for sending you on a wild goose hunt
<FromGitter> <Blacksmoke16> er maybe not
<repo> *Chase
<FromGitter> <Blacksmoke16> > Error: no overload matches 'Athena::Serializer::Serializer#deserialize' with types Granite::Base+.class, Symbol, Athena::Serializer::DeserializationContext
<repo> hmm
<repo> ...
<repo> i'm just so stupid :D
<repo> data is missing
<FromGitter> <Blacksmoke16> just noticed that
<FromGitter> <Blacksmoke16> well done :p
<FromGitter> <Blacksmoke16> also fwiw you should use DI, so like ⏎ ⏎ ``` def initialize( ⏎ @serializer : ASR::SerializerInterface, ⏎ ); end``` ⏎ ⏎ then use `@serializer` versus `ASR.serializer` [https://gitter.im/crystal-lang/crystal?at=6006eac7cf8b8277343e71f8]
<FromGitter> <Blacksmoke16> much easier to test if you're writing those 😉
<FromGitter> <Blacksmoke16> i guess it pays to read the compiler errors ha
<repo> heh yeah
<repo> Blacksmoke16: do you use a file watcher to automatically build and run your crystal webapps?
<FromGitter> <Blacksmoke16> not usually, but `nodemon` works quite well for that
<repo> nodemon? mhm will check it out
<repo> ugh, js
<FromGitter> <Blacksmoke16> :shrug: it works well
<FromGitter> <Blacksmoke16> `nodemon --exec crystal run --watch src src/main.cr`
<FromGitter> <anapsix> 👋 ⏎ I'm guessing this is not a bug, but why does it work this way? ⏎ https://play.crystal-lang.org/#/r/aa1l
<FromGitter> <Blacksmoke16> you're using structs
<FromGitter> <Blacksmoke16> they're passed by copy and intended to be immutable. if you want/need to alter them after deserialization use a class
<FromGitter> <anapsix> oh boy.. stucted again
<repo> struct struck again
<FromGitter> <anapsix> after reading https://crystal-lang.org/reference/guides/performance.html#use-structs-when-possible ⏎ I'm like, ok.. got it.. always use "structs"
<FromGitter> <Blacksmoke16> > You shouldn't always use a struct, though. Structs are passed by value, so if you pass one to a method and the method makes changes to it, the caller won't see those changes, so they can be bug-prone. The best thing to do is to only use structs with immutable objects, especially if they are small.
<FromGitter> <Blacksmoke16> second paragraph :P
<FromGitter> <anapsix> yeah... who reads that far :P
<FromGitter> <anapsix> 🙇
<FromGitter> <anapsix> 🙇 🙇
<FromGitter> <asterite> yeah, we should change that doc to say "use classes when possible" :-)
<yxhuvud> or simply not have a neutral headline and describe the down and upsides of structs for those that actually read the details :)
<yxhuvud> -not.
<FromGitter> <anapsix> ok, ok.. that's fair
<FromGitter> <asterite> Maybe it should say "Use structs for small, immutable data types", and then also mention the `record` macro
<FromGitter> <anapsix> `record` is awesome, learned about it from @Blacksmoke16 the other day
<yxhuvud> That'd make sense.
<repo> Blacksmoke16: how would you handle authentication in athena? with listeners?
<FromGitter> <Blacksmoke16> didnt get to security related abstractions yet, so have to do some stuff on your own for now
<straight-shoota> ,
<repo> this bothers me a bit: `if event.request.method == "POST" && {"/user", "/login"}.includes? event.request.path`
<FromGitter> <Blacksmoke16> mhm
<repo> i'd like to define this in the controller/action
<repo> hm maybe i'll do it with a converter instead
<FromGitter> <Blacksmoke16> i think we're talking about two diff things. that cook book example is for authentication. I.e. resolving a user from some form of token or something
<repo> yeah, that's what i want
<FromGitter> <Blacksmoke16> sounds like you want to add authorization logic to specific routes
<repo> oh yeah
<FromGitter> <Blacksmoke16> could probably do something like the pagination example. I.e. define some custom annotation that can be applied to specific routes that store data on the security "level", then would be able to check for that against the current user
<repo> mhm
<FromGitter> <Blacksmoke16> i really like the pagination example. Is one of the super cool things i like that im proud of 😆
<FromGitter> <Blacksmoke16> not sure how you'd go about doing that in other frameworks 😉
<repo> that's reeeeally cool *.*
<FromGitter> <mattrberry> Ty Ary :)
xaxisx has joined #crystal-lang
<raz> this m1 is a bit silly. "warning, your mac will sleep soon". 10% battery remaining. that's 2 hours lol
<FromGitter> <Blacksmoke16> more like new battery
<raz> yea the battery is nuts. 20h on full charge
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 256 seconds]
alexherbo2 has joined #crystal-lang
mertyildiran has joined #crystal-lang
<FromGitter> <dansimpson> Hey folks, I am having some trouble with a multi-arch build. I am using docker to compile my program statically, and it works great for x64 using crystallang/crystal:0.35.1-alpine ... however, I can't find a matching aarch64 version of that image. When I use jhass/crystal:0.35.0-build-aarch64 which I found in the github workflows code, it doesn't seem to work. Is there an equivalent docker image to
<FromGitter> ... crystallang/crystal:0.35.1-alpine for arm architectures? I think part of this is my weak docker knowledge as well. Thanks.
alexherbo2 has quit [Ping timeout: 256 seconds]
<FromGitter> <jrei:matrix.org> @dansimpson: All I know about is: https://gist.github.com/j8r/34f1a344336901960c787517b5b6d616
<FromGitter> <dansimpson> @j8r thanks let me check that out
<FromGitter> <jrei:matrix.org> I updated the gist to have working libraries, but long time I didn't fully run the script
<repo> Blacksmoke16: hmm are uuids as foreign keys not supported in granite?
<repo> (as UUID type)
alexherbo2 has joined #crystal-lang
<FromGitter> <Blacksmoke16> im 80% sure they are
<FromGitter> <Blacksmoke16> but might need a converter?
<repo> yeah
<FromGitter> <Blacksmoke16> oh as foreign keys
<repo> exactly :)
<FromGitter> <Blacksmoke16> i dont really remember
<repo> it looks like adding converter: ... to belongs_to doesn't make any difference
<FromGitter> <Blacksmoke16> fwiw `belongs_to` just defines like a method or 2, could just define that method manually
<repo> mmh i guess
<FromGitter> <Blacksmoke16> :shrug:
<repo> weird though.. i mean uuids are generally supported but not as foreign keys?
<FromGitter> <Blacksmoke16> been a while since i looked at granite code
<FromGitter> <Blacksmoke16> could just have been an oversight
<repo> should be easy enough to fix
<FromGitter> <Blacksmoke16> 👍
<repo> Blacksmoke16: yup, was really ezpz! https://github.com/amberframework/granite/pull/438
<FromGitter> <Blacksmoke16> nice one!
<FromGitter> <dansimpson> It is close to working! I am just getting errors about gc, -lz not found. I'll see if I can figure it out and let you know.
<FromGitter> <dansimpson> Adding zlib-dev and zlib-static fixed it up for me.
<FromGitter> <jrei:matrix.org> thanks! updating the gist :)
<FromGitter> <jrei:matrix.org> I think it depends if the application uses HTTP
<FromGitter> <dansimpson> Yeah, it does depend on stdlib usage
<FromGitter> <dansimpson> the zlib-static was the piece there that got it working
<FromGitter> <dansimpson> thanks for the gist!
<FromGitter> <jrei:matrix.org> 🙂
<FromGitter> <jrei:matrix.org> I can't find jhass' Dockerfile either. It used qemu too
MasterdonX has joined #crystal-lang
_ht has quit [Ping timeout: 265 seconds]
_ht has joined #crystal-lang
xaxisx has quit [Quit: Leaving...]
_ht has quit [Remote host closed the connection]
<repo> Blacksmoke16: how would I define which groups to use for serialization in a controller action?
<FromGitter> <Blacksmoke16> https://athenaframework.org/Routing/View/
<repo> ahh
<repo> sweet
<FromGitter> <Blacksmoke16> 👍
r0bby has quit [Read error: Connection reset by peer]
r0bby has joined #crystal-lang
<repo> Blacksmoke16: the update method in https://athenaframework.org/cookbook/param_converters/ only works for replacements, right? not partial updates?
<repo> but it seems params not present in the json will be overwritten with nil
<FromGitter> <Blacksmoke16> hmm
<FromGitter> <Blacksmoke16> ill have to think about that one
<FromGitter> <Blacksmoke16> from what i can tell they should be ignored
<repo> hm
<repo> nonetheless i get Save Exception: Bucket::Models::Token#user_id cannot be nil
<repo> and i haven't sent user_id in the request. it's also not in the "update" group
<repo> or is that the problem? everything not in the given groups will be set to nil?
<repo> oh
<repo> it's something else
<repo> hm the object constructor isn't used at all
<repo> maybe because i never required the file! time to go to bed... m(
<FromGitter> <Blacksmoke16> :S sounds like it ha
<repo> oh boy oh boy
<repo> Blacksmoke16: damn, i'm so impressed by athena
<repo> it's quite a steep learning curve but every time i need something done it kind of falls into place in a beatiful way in the end. I can really tell that a lot of thought has been put into it. Even more astonishing, as you've done it all by yourself.
<FromGitter> <Blacksmoke16> ❤️ After a while i should hope everything clicks :) Benefit is you dont need learn it all at once, only when you need that feature
<FromGitter> <Blacksmoke16> but i cant take all the credit...kinda just ported an existing framework into Crystal ha
<repo> still, awesome stuff!
tankf33der has left #crystal-lang ["the lounge - https://webirc.envs.net"]
<FromGitter> <Blacksmoke16> i try :)