RX14 changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.27.1 | Fund Crystal's development: http://is.gd/X7PRtI | GH: https://github.com/crystal-lang/crystal | Docs: http://crystal-lang.org/docs/ | API: http://crystal-lang.org/api/ | Gitter: https://gitter.im/crystal-lang/crystal
fullforce has quit [Quit: leaving]
<FromGitter> <asterite> specially the limitations part
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/68as would be nice
jemc has quit [Quit: WeeChat 2.2]
<FromGitter> <Blacksmoke16> also would be nice to have optional dependencies in shards
<FromGitter> <Blacksmoke16> that are required for specific portions of code to work but otherwise not needed
<FromGitter> <Blacksmoke16> which would tie into the `check if a shard is installed` macro, as if someone does `require "myApp/feature"` could throw compile error if that required shard is not installed
<FromGitter> <Blacksmoke16> i guess it could be argued to just use separate shards but can be kinda overkill imo
<FromGitter> <girng> i'
<FromGitter> <girng> i'm getting `Unhandled exception in spawn: connect: Connection refused (Errno)` with `sock = UNIXSocket.new("pipe.sock")`
<FromGitter> <girng> this is happening on native linux too, not just WSL. i don't have any sockets open except for the main socket server that is on port 9300 (master server)
fullforce has joined #crystal-lang
<fullforce> asterite: got your message, power cut out
<fullforce> what should I use?
<fullforce> @@sock = TCPSocket.new ?
johndescs has quit [Ping timeout: 240 seconds]
johndescs has joined #crystal-lang
<FromGitter> <Blacksmoke16> https://editor.swagger.io/?_ga=2.257973506.965035947.1549942252-553464429.1549942252 sneak peak of built in OpenAPI generation via `Athena`
<FromGitter> <Blacksmoke16> plan is to combine the required stuff for route definitions plus an optional annotation or something to build it out (for the most part) with minimal effort
fullforce has quit [Quit: leaving]
<FromGitter> <Blacksmoke16> Peek*
<FromGitter> <girng> O_O
early has quit [Quit: Leaving]
early has joined #crystal-lang
early has quit [Quit: Leaving]
early has joined #crystal-lang
<FromGitter> <girng> WOW this is awesome. i just setup a *local* TCPServer on a diff port, and then utilize `shell_exec("bash -c 'echo ${user_id} >/dev/tcp/127.0.0.1/9305'");` in php to notify my crystal process
<FromGitter> <j8r> You can't write in a file with PHP other than creating a bash subprocess?! I don't believe it
DTZUZO has quit [Ping timeout: 268 seconds]
badeball_ is now known as badeball
ashirase has quit [Ping timeout: 245 seconds]
ashirase has joined #crystal-lang
<FromGitter> <alex-lairan> Hey hello everyone :D ⏎ ⏎ New day, new question :D ⏎ ⏎ I have a hash who contain a class ... [https://gitter.im/crystal-lang/crystal?at=5c62a697dc3f0523cca07560]
<FromGitter> <j8r> a hash or a named tuple?
<FromGitter> <j8r> hum I doesn't matter, that's a HashLiteral right?
<FromGitter> <alex-lairan> Yes
<FromGitter> <alex-lairan> `{} of Nil => Nil`
<FromGitter> <alex-lairan> (But nil doesn
<FromGitter> <j8r> `if opts[:klass].is_a? Array`
<FromGitter> <alex-lairan> I can't without macro, because the `as` will be build for both
<FromGitter> <j8r> inside the macro i mean
<FromGitter> <j8r> nvm
<FromGitter> <alex-lairan> ```code paste, see link``` ⏎ ⏎ What is `Path` :o [https://gitter.im/crystal-lang/crystal?at=5c62a8faecef85660b91212a]
<FromGitter> <sfcgeorge> Implementors may already be aware of this but when wanting to add a new Ruby feature to Crystal the code of this gem might help https://github.com/marcandre/backports As it implements new Ruby features for older Rubies in pure Ruby (not C) it should make porting to Crystal clearer.
<FromGitter> <alex-lairan> This work : ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c62bf86adf6cb0b2ca6b0ce]
<FromGitter> <Blacksmoke16> what happens if you have `Array(String)?`
<FromGitter> <Blacksmoke16> i think that might break your logic @alex-lairan
<FromGitter> <Blacksmoke16> since there is no `#resolve` method on type `Union`
<FromGitter> <alex-lairan> `undefined macro method 'Union#resolve'` you are right :/
<FromGitter> <Blacksmoke16> `{% nilable = arg.restriction.is_a?(Union) ? !arg.restriction.types.any?(&.resolve.nilable?) : arg.restriction.is_a?(Path) ? !arg.restriction.resolve.nilable? : !arg.restriction.nilable? %}`
<FromGitter> <Blacksmoke16> could do something similar :/
<FromGitter> <alex-lairan> This could work, but what if `Array(String) | String`, this will not work. ⏎ ⏎ I think the best I have to do is to forbid `Union` types. ⏎ ⏎ For my ORM I already provide two getter ... [https://gitter.im/crystal-lang/crystal?at=5c62c595dc3f0523cca15afd]
<FromGitter> <Blacksmoke16> :shrug: or just handle the extra logic
<FromGitter> <Blacksmoke16> on another topic, had a thought that i could prob generate athena controllers/actions from a swagger.yml/json files
<FromGitter> <Blacksmoke16> that would be neat
DTZUZO has joined #crystal-lang
<FromGitter> <j8r> I can't do `myvar.as(Hash(Char, _))`
<FromGitter> <bew> `.as(SomeType)` is not the same as using `SomeType` as a restriction
<FromGitter> <bew> restrictions are much permissive
<FromGitter> <bew> `.as` tries to 'set' the type of `myvar`, it must be a fully defined type
<FromGitter> <Prutheus> I have something like this: `data["sellerInfo"][0]["bidCount"][0].as_s` but when the hash key `”sellerInfo”` is missing, how can I then stop this line and not raise an exception?
<FromGitter> <j8r> `data["sellerInfo"]?.try &.[0]["bidCount"][0].as_s`
<FromGitter> <Sija> @Prutheus `data.dig?("sellerInfo", 0, "bidCount", 0)`
<FromGitter> <Prutheus> nice
<FromGitter> <Prutheus> Is it also possible to do that? `result.data.dig?("sellerInfo", 0, "sellerUserName", 0)?.try &.as_s` I get error : `unexpected token: .` at `?.try`
<FromGitter> <Blacksmoke16> i dont think you need the `?` at the end of `dig?`
<FromGitter> <j8r> You can also use JSON.mapping or JSON::Serializable, if it is JSON
<FromGitter> <j8r> It'll simplify your life
jemc has joined #crystal-lang
<FromGitter> <Sija> @Prutheus it is, but as @Blacksmoke16 mentioned, that's one `?` too much :)
<FromGitter> <Sija> `result.data.dig?("sellerInfo", 0, "sellerUserName", 0).try &.as_s`
<FromGitter> <Sija> `?` here is part of the method name (`dig?`), not a language construct (like say in CoffeeScript)
<FromGitter> <Prutheus> I have the problem that I want to use this: `result.data.dig?("sellerInfo", 0, "bidCount", 0).try &.as_s.empty? ? NO_DATA : result.data.dig("sellerInfo", 0, "bidCount", 0)` and NO_DATA should be reached when dig returns nil or the string is empty
<FromGitter> <Prutheus> but how to do that, not with my method
<FromGitter> <Blacksmoke16> could use the json serializable stuff and deserialize your json into structs or something
<FromGitter> <Blacksmoke16> would depend on how the data is structured tho
<FromGitter> <Blacksmoke16> otherwise prob would have to break that up a bit
<FromGitter> <Blacksmoke16> got some example json or something?
<FromGitter> <bararchy> BTW do we have a good way to JSON#as_xml ?
<FromGitter> <Sija> @bararchy There's `XML::Builder` but nuffin' like `Object#to_xml`, nope
<FromGitter> <Blacksmoke16> i was working on that
<FromGitter> <Sija> well, you can't have it generalized since generating XML is bit moar complex than JSON or YAML
<FromGitter> <Sija> say, how would you (de)serialize arrays or other compound types?
<FromGitter> <Blacksmoke16> yea sadly, main challenge is array of objects vs array of scalar values like string
<FromGitter> <Blacksmoke16> and from_xml would be a pita
<FromGitter> <Sija> that's why Apple came up with their own PLIST format which standarizes that shit, while still using XML underneath
<FromGitter> <Blacksmoke16> go does it by wrapping each array value in a tag thats has the name of the array property
<FromGitter> <Sija> hmm, so how would `%w(foo bar)` be serialized in such case?
<FromGitter> <Blacksmoke16> ```<xml ...> ⏎ <item>foo</item> ⏎ <item>bar</item>``` [https://gitter.im/crystal-lang/crystal?at=5c62f5c14bafd97ca3dd8108]
<FromGitter> <Blacksmoke16> ?
<FromGitter> <Blacksmoke16> would have to see how other langs handle it i guess :shrug:
<Yxhuvud> I don't see why we would provide a default mapping between json and xml at all.
<FromGitter> <Blacksmoke16> https://play.golang.org/p/O9oi1UCREej @Sija
<FromGitter> <Blacksmoke16> its not between json and xml
<FromGitter> <Blacksmoke16> it would be similar to `to_json` or `to_yaml` to be obj => serialization format
<FromGitter> <Blacksmoke16> looks like they just use type name as key
<FromGitter> <Sija> yep, fair 'nuff. yet it's still a convention (albeit I'd agree pretty sensible one)
<FromGitter> <Blacksmoke16> prob play with it more, prob would add it to my shard first
<FromGitter> <Blacksmoke16> dont know if it would be wanted int stdlib if there is talk of moving that stuff out
<FromGitter> <Blacksmoke16> to_xml would be far easier than from_xml imo
<FromGitter> <Blacksmoke16> esp since i know like nothing about the XML::Reader or whatever
markoong has joined #crystal-lang
<FromGitter> <Sija> IMHO `to/from_plist` would make more sense since it's some standard you can build on, whereas XML has none apart from some conventions used here and there...
rohitpaulk has joined #crystal-lang
<FromGitter> <Blacksmoke16> possibly
rohitpaulk has quit [Ping timeout: 245 seconds]
Vexatoast has joined #crystal-lang
Vexatos has quit [Ping timeout: 246 seconds]
fullforce has joined #crystal-lang
<FromGitter> <j8r> I was searching where is IntegerLiteral, but it's NumberLiteral
<FromGitter> <j8r> How can I have an Array of MacroDef?
<FromGitter> <j8r> I don't understand because I can do https://play.crystal-lang.org/#/r/68fv
<FromGitter> <j8r> I think i got it
<FromGitter> <j8r> I'm still figuring how to do
_whitelogger has quit [Remote host closed the connection]
_whitelogger has joined #crystal-lang
FromGitter has joined #crystal-lang
<mps> after some contemplation about "Programming Crystal" I must write my apology to the authors and publisher. For not a much money I have guides which are dispersed over net in one place and organized from simple to more complex features of language, and with nice interviews with people who successfully deployed crystal in their applications
<mps> sorry again for impolite words
<FromGitter> <vladfaust> Do you agree that syntax is pretty clean? https://carc.in/#/r/68ia
fullforce has quit [Remote host closed the connection]
<FromGitter> <dscottboggs_gitlab> ooh, is that a middleware that would respond to like a `POST /articles/comments/create` reqest?
<FromGitter> <dscottboggs_gitlab> yes, I like the syntax
dostoyev1ky has quit [Quit: leaving]
dostoyevsky has joined #crystal-lang
<FromGitter> <vladfaust> The action thing, yes, it's a REST endpoint
<FromGitter> <vladfaust> The app could look like this: https://carc.in/#/r/68ib
<FromGitter> <dscottboggs_gitlab> and it's the `params do...` verification syntax you're asking about?
<FromGitter> <dscottboggs_gitlab> or just the whole thing?
<FromGitter> <mettuaditya> can anyone send me link on coverage tool
<FromGitter> <dscottboggs_gitlab> There isn't a working one as of yet I don't believe. I found one one time but it wasn't up-to-date and didn't seem to work.
<FromGitter> <Blacksmoke16> https://github.com/anykeyh/crystal-coverage is only one i know of
<FromGitter> <dscottboggs_gitlab> coverage is hard man
<FromGitter> <Blacksmoke16> but dont know first hand if its working
<FromGitter> <vladfaust> Just the whole picture :)
<FromGitter> <mettuaditya> ohh.. thanks for the information
<FromGitter> <dscottboggs_gitlab> np @mettuaditya
<FromGitter> <Blacksmoke16> is some inherit knowledge required to know what is going on in some points
<FromGitter> <Blacksmoke16> but prob easily enough understood with sufficient docs
<FromGitter> <vladfaust> It now works on top of Onyx and SQLite. On my machine atm, gonna publish in days
<FromGitter> <vladfaust> Along with the detailed tutorial of how to recreate the Crystal World by yourself :)
<FromGitter> <dscottboggs_gitlab> @vladfaust I like the way the code is organized, it's obvious at a glance that it's a middleware module which creates a comment. The `params do...` syntax is nice but seems a bit...long or verbose? Idk, I kinda like @Blacksmoke16's annotation based param validation better, but I also like the way that one is.
<FromGitter> <dscottboggs_gitlab> If only annotations weren't so ugly.....
<FromGitter> <vladfaust> The matter of preference, I guess. I love using annotations but I think they're ugly and I'm trying to hide them under macros DSL :)
<FromGitter> <dscottboggs_gitlab> yes that is exactly the issue lol
<FromGitter> <vladfaust> Their syntax may be scary for newcomers
<FromGitter> <vladfaust> They'd prefer a beautiful DSL instead
<FromGitter> <dscottboggs_gitlab> I stumbled on a great syntax idea yesterday... `:>`. I had been thinking of recommending `|>` for a while but I like `:>` even more.
<FromGitter> <dscottboggs_gitlab> Yeah I really think it's just the wierd syntax -- lots of languages have annotations
<FromGitter> <dscottboggs_gitlab> Although they usually work differently than in Crystal
<FromGitter> <vladfaust> `:>` for what? `:>Annotation`?
<FromGitter> <dscottboggs_gitlab> yeah, like ⏎ ⏎ ```:> JSON::Field key: "SomeKey" ⏎ def some_key ⏎ ... ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5c633d2f4003460b2d3ddad0]
<FromGitter> <dscottboggs_gitlab> The `|>` operator from F# is pretty clear syntactically though
* FromGitter * vladfaust shuddered
<FromGitter> <Blacksmoke16> ```# @JSON::Field(key: "SomeKey") ⏎ def some_key ⏎ ... ⏎ end``` ⏎ ⏎ Is what im a fan of imo [https://gitter.im/crystal-lang/crystal?at=5c633d5a8328315dece3968f]
<FromGitter> <dscottboggs_gitlab> "pipe this method through the annotation"
<FromGitter> <dscottboggs_gitlab> TBH I hadn't written out an example like that and upon looking at it I hate it too lol
<FromGitter> <Blacksmoke16> :P
<FromGitter> <vladfaust> @Blacksmoke16 nah, docs should not affect the code
<FromGitter> <dscottboggs_gitlab> agreed, I don't like comments-as-code
<FromGitter> <Blacksmoke16> 😬
<FromGitter> <dscottboggs_gitlab> maybe this ⏎ ⏎ ```|> JSON::Field key: "SomeKey" ⏎ def some_key ⏎ ... ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5c633dad253c2b5ea3005715]
<FromGitter> <dscottboggs_gitlab> That's not much better but it fits with Crystal's operator-focused syntax
<FromGitter> <dscottboggs_gitlab> Ugh, I guess nothing's good enough to be worth breaking everything at this point
<FromGitter> <Blacksmoke16> unless the implementation i dont see how you could get much better than `@[JSON::Field(key: "key")]` i mean its not *that* bad imo
<FromGitter> <vladfaust> We just got used to it
<FromGitter> <Blacksmoke16> ```<< JSON::Field key: "SomeKey" >> ⏎ def some_key ⏎ ... ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5c633e2e8328315dece39cef]
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <vladfaust> I guess *any* annotation-like functionality is ugly
<FromGitter> <dscottboggs_gitlab> Does ruby have annotations?
<FromGitter> <Blacksmoke16> php does it on comments, hence why im used to those
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c633e5ad1e3093ab50d7075]
<FromGitter> <vladfaust> Because it steps out from traditional declaration of methods and objects
<FromGitter> <vladfaust> PHP example is strange. Isn't that just a syntax for doc generation?
<FromGitter> <vladfaust> Does it actually affect the code?
<FromGitter> <Blacksmoke16> not that particular example
<FromGitter> <dscottboggs_gitlab> ```||| JSON::Field key: "SomeKey" ⏎ def some_key ⏎ ... ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5c633e945095f6660ce2c7ec]
<FromGitter> <dscottboggs_gitlab> nope
<FromGitter> <vladfaust> I mean, don't take PHP as a good language in this case
<FromGitter> <vladfaust> `|||||| JSON::Field key: "SomeKey"`
<FromGitter> <vladfaust> Should do the case
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c633ea8126af75deb968b23]
<FromGitter> <Blacksmoke16> that one does
<FromGitter> <Blacksmoke16> is what inspired my shard
<FromGitter> <vladfaust> And how do you differ between "non-affecting" `@param` and "affecting" `@Type`
<FromGitter> <dscottboggs_gitlab> See, on first glance I would think those were just weird doc-builder directives
<FromGitter> <vladfaust> Casing?
<FromGitter> <Blacksmoke16> just gotta know i guess? as with any lang
<FromGitter> <vladfaust> Okay then, but I don't like it
<FromGitter> <elorest> I think the syntax is fine, as long as we don’t use them everywhere. Are there like specific use cases where they make the most sense or is the current fad to just “Annotate all the things”?
<FromGitter> <Blacksmoke16> afaik they are they preferred way to add compile time info to types, e.x. methods/properties/classes
<FromGitter> <dscottboggs_gitlab> They tend to be more flexible and powerful than DSL's since you have to define all your types at compile time anyway
<FromGitter> <Blacksmoke16> which i like that they are kinda "universal" in that its easy to tell what they are applied to, and if every serialization lib for example supported them changing which one you use would just be a matter of changing the annotation, and not have to worry about shard specific macros
<FromGitter> <Blacksmoke16> so like everything kinda just "works"
<FromGitter> <Blacksmoke16> vs i need this macro DSL for my ORM, this one for my REST API, this one for my validation/serialization
<FromGitter> <Blacksmoke16> when they all pretty much are doing the same thing
<FromGitter> <dscottboggs_gitlab> that's a really good point
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c6340054bafd97ca3dfb6dd]
<FromGitter> <Blacksmoke16> something like that would be my pipedream
<FromGitter> <dscottboggs_gitlab> why not just have an `annotate` keyword? Like ⏎ ⏎ ```annotate JSON::Field key: "SomeKey" ⏎ def some_key ⏎ ...``` [https://gitter.im/crystal-lang/crystal?at=5c63402c80df6804a1940392]
<FromGitter> <Blacksmoke16> would be more clear of what it is, but longer to type?
<FromGitter> <dscottboggs_gitlab> and less ugly, which is my big gripe
<FromGitter> <dscottboggs_gitlab> I'd say have both but Crystal is anti-alias
moei has quit [Quit: Leaving...]
<FromGitter> <elorest> Hmmm. When I tried using annotations instead of macro’s a couple months back it really seemed like I was trying to pound a square peg into a round hole, plus it seemed to clutter up namespace with a bunch of single use module definitions. ⏎ ⏎ Faster is better though.
<FromGitter> <dscottboggs_gitlab> it definitely depends on the use-case IMO, and annotation-based macros are definitely harder to write and require more knowledge about that area of Crystal than just a regular DSL
<FromGitter> <Blacksmoke16> aye
<FromGitter> <Blacksmoke16> __JSON::Field key: "SomeKey" ⏎ def some_key ⏎ ... ⏎ end [https://gitter.im/crystal-lang/crystal?at=5c63411ed1e3093ab50d826d]
<FromGitter> <Blacksmoke16> meh
<FromGitter> <dscottboggs_gitlab> yeah I always think I have these great idas and then I write it out and it's like "well that's not that much better"
<FromGitter> <Blacksmoke16> it requires a diff way of thinking, plus annotations are not a replacement to macros
<FromGitter> <Blacksmoke16> you need macros to get the annotations
<FromGitter> <dscottboggs_gitlab> A really easy change that would make a big difference is not requiring the parentheses within the annotation
<FromGitter> <Blacksmoke16> its just an alternative way to "storing" the data, vs having a macro DSL build out a method/property, just have the annotation on the method/property
<FromGitter> <Blacksmoke16> is that a requirement atm?
<FromGitter> <elorest> More knowledge is fine as long as it’s easy for the end user of libraries to use. My concern is that people come to crystal because it’s beautiful syntax plus speed. If the code all ends up looking like @Blacksmoke16 ’s ORM example above, then rust starts to look a lot more palatable.
<FromGitter> <dscottboggs_gitlab> yes
<FromGitter> <dscottboggs_gitlab> > If the code all ends up looking like @Blacksmoke16 ’s ORM example above, then rust starts to look a lot more palatable. ⏎ ⏎ this ☝️
<FromGitter> <Blacksmoke16> depends on what the user things is `beautiful syntax`
<FromGitter> <dscottboggs_gitlab> ```ann JSON::Field key: "SomeKey" ⏎ def some_key ⏎ ... ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5c63422cecef85660b95ab4e]
<FromGitter> <Blacksmoke16> needs to be differentiated from the `property` keyword
<FromGitter> <Blacksmoke16> else it just blends
<FromGitter> <Sija> sorry, to me it looks just ugly - some weird mix between Java and PHP
<FromGitter> <dscottboggs_gitlab> which, `annotate`?
<FromGitter> <Sija> 10 lines to express sth that can fit in 1
<FromGitter> <Blacksmoke16> and what would that one line look like?
<FromGitter> <Sija> well, overusing them as given in @Blacksmoke16's example
<FromGitter> <vladfaust> You can hide them under macros
<FromGitter> <vladfaust> E.g. https://carc.in/#/r/68ii
<FromGitter> <vladfaust> `schema` attaches annotations to instance variables and the type
<FromGitter> <vladfaust> Passing options to them as is (i.e. `key: ""`)
<FromGitter> <Blacksmoke16> :shrug: guess im not just a fan of the middleman step there
<FromGitter> <Sija> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c6342e8a59de252b04ea8e8]
<FromGitter> <Blacksmoke16> seems redundant to create a whole unique DSL when `property` keyword + annotation gets you the same thing
<FromGitter> <Blacksmoke16> thats my main gripe i think
<FromGitter> <Blacksmoke16> https://gitter.im/crystal-lang/crystal?at=5c633f907502282258e1cb74 going back to that
<FromGitter> <Sija> redundant for someone creating a library, perhaps but definately nicer for an end-user
<FromGitter> <paulcsmith> A lot of times I'd rather create a separate object than overload properties with lots of annotations. But that may be just me
<FromGitter> <Sija> bear in mind that people love Crystal for its syntax and brevity
<FromGitter> <paulcsmith> Annotations are helpful, but I think a lot of times it may mean a class is getting stuffed with too many responsibilities that may be better to split out instead. So one class handles models, another serialization, etc. Rather than one class doing all of it
<FromGitter> <Sija> @Blacksmoke16 "if every serialization lib for example supported them changing which one you use would just be a matter of changing the annotation, and not have to worry about shard specific macros" if… ;)
<FromGitter> <Blacksmoke16> *in a perfect world*
<FromGitter> <Sija> yeah, exactly
<FromGitter> <Blacksmoke16> one can dream :P
<FromGitter> <dscottboggs_gitlab> ☝️ February 12, 2019 5:06 PM (https://gitter.im/crystal-lang/crystal?at=5c634350ef98455ea425959e) true, I tend to create a `SomeClass::Serialized` subclass or something like that which handles that stuff for me
<FromGitter> <Blacksmoke16> @paulcsmith yea, i like to write the least amount of code i can
<FromGitter> <Blacksmoke16> so one class that handles everything nicely is my preference
<FromGitter> <paulcsmith> One downside to that approach is it can make it hard to extend. For example, what happens when you have two JSON serializers. One for v1 of the api and one for v2. What do you do?
<FromGitter> <paulcsmith> If you have separate classes you create a new class. If you use annotations you have serialization happening in the main class and in some other class. That is ok, but it is a tradeoff
<FromGitter> <dscottboggs_gitlab> oh wow, haven't run into that yet
<FromGitter> <dscottboggs_gitlab> that would certainly be an issue
<FromGitter> <Blacksmoke16> in my perfect world each one would have their own annotation that each lib would know how to implement
<FromGitter> <Blacksmoke16> or if using CrSerializer would be a perfect use of https://github.com/Blacksmoke16/CrSerializer/blob/master/docs/serialization.md#serialization-groups
<FromGitter> <Blacksmoke16> https://github.com/Blacksmoke16/athena/blob/master/docs/routing.md#groups which would directly map to this, if you had an api framework that supported such a concept
<FromGitter> <Blacksmoke16> and it would be that easy, no need to have new classes here and there
<FromGitter> <paulcsmith> This is indeed less code, but I feel that it is difficult to parse. I think with a reasonably sized serializer it would be difficult to figure out what "admin" renders. Those annotations could be all over
<FromGitter> <paulcsmith> I think this may just be a different viewpoint. I just think annotations have their pros and cons. And for some people the downsides may not be worth it.
<FromGitter> <Blacksmoke16> it would just render properties on the `User` class that are part of that group
<FromGitter> <Blacksmoke16> which can easily be seen by looking at return type of the action
<FromGitter> <Blacksmoke16> pretty much
<FromGitter> <Blacksmoke16> > Those annotations could be all over ⏎ Thats the point of having everything in the one `User` class. the its all centralized
<FromGitter> <Blacksmoke16> but we're arguing semantics atm
<FromGitter> <paulcsmith> Maybe. Personally I think something like this: https://gist.github.com/paulcsmith/6a2d8596f985baf8bbf692973fef13d9 is difficult to read. It would be hard to look at that class and visualize what an "admin" would look like since they are now scattered on multiple lines. And this is with a fairly small serializer.
<FromGitter> <paulcsmith> I think to some degree this comes down to preference is what I'm getting at. Annotations are not necessarily better or worse
<FromGitter> <Blacksmoke16> aye, also comes down to if it was your codebase you would know what an "admin" represents
marius has joined #crystal-lang
<FromGitter> <Blacksmoke16> vs an abstract example w/o context
<FromGitter> <paulcsmith> Yeah that is true. For smaller teams this may be perfect to use annotations. But for medium sized teams it is unlikely everyone would know what all the serializers look like
<FromGitter> <paulcsmith> In which case something like this is nice IMO https://gist.github.com/paulcsmith/c372d1fd5a8ad7a879f47c258856efa2
<FromGitter> <dscottboggs_gitlab> Yeah, I have to agree. I think there are a lot of cases where annotations make sense, but a `group "group name" do...` DSL would be a lot nicer for his example.
<FromGitter> <paulcsmith> Because you can look at it and see only what an admin should look like
<FromGitter> <dscottboggs_gitlab> oof would that even work? ugh
<FromGitter> <paulcsmith> Or yeah a group macro or something
<FromGitter> <paulcsmith> I dunno if it'd work but something like that would definitely help
<FromGitter> <Blacksmoke16> now we're back to `so like everything kinda just "works" vs i need this macro DSL for my ORM, this one for my REST API, this one for my validation/serialization`
<FromGitter> <Blacksmoke16> :P
<FromGitter> <Blacksmoke16> which in the end it doesnt really matter, whatever works for you
<FromGitter> <dscottboggs_gitlab> well, no, Paul's exaple just inherits from a certain type which defines the macros by default.
<FromGitter> <paulcsmith> You can not use annotations and still not have a DSL
<FromGitter> <paulcsmith> Yeah exactly
<FromGitter> <paulcsmith> It has almost no macros. It is basically one method that returns a data object. Super easy to extend. You can downcase or do whatever you want to values.
<FromGitter> <paulcsmith> It is not perfect, but it is not some giant DSL :P
<FromGitter> <Blacksmoke16> yea fair enough
<FromGitter> <dscottboggs_gitlab> I like how `JSON::Serializable` et al do it, where annotations are available for options but there are sensible defaults which don't require annoations
<FromGitter> <Blacksmoke16> ^
<FromGitter> <vladfaust> ^
<FromGitter> <Blacksmoke16> is how i tried to setup my stuff, ability to expand upon but sensible defaults
<FromGitter> <dscottboggs_gitlab> if every property needs an annoation, I feel like there's probably a better way to do it, like inheriting from a type which defines macros based on it's `instance_whatever`s or a DSL.
<FromGitter> <paulcsmith> Another problem I've had with ActiveModel Serializers and similar "put it all in one spot" thing is that it can be hard to expand. For example. How would you add the number of todos to a todos serializer with annotations?
<FromGitter> <Blacksmoke16> hence, properties w/o annotation are assigned `default` group, so its not like you *have* to annotation everything, just those that need it
<FromGitter> <dscottboggs_gitlab> or including a module
<FromGitter> <paulcsmith> You could add a property like `count` but then it'd need to be nilable since sometimes you don't care about that. This is the main problem I have with stuffing classes with stuff. It can quickly break when new stuff is added which leads to weird hacks, nilable values, etc.
<FromGitter> <paulcsmith> However this is not the case with all projects. Just something I think people should keep in mind when deciding on one route v. the other
<FromGitter> <Blacksmoke16> id have to test it but something like
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c6347b98328315dece3e0c0]
<FromGitter> <paulcsmith> Yeah, so now you have a nilable value which will almost certainly lead to bugs
<FromGitter> <paulcsmith> You could forget to pass the count in one call and then your users would get `count: nil`
<FromGitter> <Blacksmoke16> you wouldnt have to touch it
<FromGitter> <Blacksmoke16> it would just be there as a virtual property for serialization
<FromGitter> <paulcsmith> By making a new class just for serializing that type of object you can set it to non nil and it would be nearly impossible to forget that
<FromGitter> <paulcsmith> Yeah but you will not get compile time guarantees
<FromGitter> <Blacksmoke16> i mean you also could set it not nil and default to 0
<FromGitter> <Blacksmoke16> hard to say without an actual example
<FromGitter> <dscottboggs_gitlab> I'm sorry, I don't understand...crystal is null-safe, you can't have a null reference bg
<FromGitter> <paulcsmith> I'll show an example. One sec
<FromGitter> <paulcsmith> It would not raise, it would just be incorrect
<FromGitter> <dscottboggs_gitlab> it would be a pain in the dick to do `if count = something.count` every time but it wouln't ever result in an error
<FromGitter> <paulcsmith> `Example.new(posts: posts).to_json` would incorrectly have `count: nill`
<FromGitter> <dscottboggs_gitlab> how?
<FromGitter> <dscottboggs_gitlab> wouldn't count be `posts.size`?
<FromGitter> <paulcsmith> It could, but you could also forget that and then introduce a bug
<FromGitter> <paulcsmith> Not a runtime error, but still a bug
<FromGitter> <dscottboggs_gitlab> fair enough
<FromGitter> <paulcsmith> Or if you had a `0` default it is the same thing, maybe worse. Because you'd accidentally send `0` when there may be more than that
<FromGitter> <dscottboggs_gitlab> yeah, why is `#count` nillable?
mps has quit [Ping timeout: 250 seconds]
<FromGitter> <dscottboggs_gitlab> I agree, that would be worse for sure
<FromGitter> <paulcsmith> This example wasn't the best, but what if I had a `User` model. It would be weird to give it a count
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c6348fedc3f0523cca54858]
<FromGitter> <paulcsmith> So `User.first` shouldn't return a user with a count because it isn't an array. This is the problem with annotations in my mind. It makes it easy to do the simple case, but when you want something a little different it forces you into things that result in fewer compile time guarantees or strange hacks
<FromGitter> <Blacksmoke16> i tried it
<FromGitter> <dscottboggs_gitlab> @Blacksmoke16 yes, in your case it worked, but bugs happen to the best of us
<FromGitter> <Blacksmoke16> yea for sure
<FromGitter> <paulcsmith> I'm also just obsessed with compile time guarantees. Not necessary but I like to make it as hard as possible to do the wrong thing. Sometimes it means a bit more code, but I think it is worth it to reduce bugs
<FromGitter> <dscottboggs_gitlab> @paulcsmith now I'm *more* confused! haha
<FromGitter> <dscottboggs_gitlab> ☝️ February 12, 2019 5:31 PM (https://gitter.im/crystal-lang/crystal?at=5c63495cdc3f0523cca54b69) all of this
<FromGitter> <Blacksmoke16> for sure
<FromGitter> <paulcsmith> I have to go right now for dinner, but I can post what I mean. I've been meaning to do a more in-depth blog post, but I'll try to post examples later
<FromGitter> <paulcsmith> Cool if I ping you guys on those (assuming your interested)
<FromGitter> <Blacksmoke16> would like to come up with ideas for how to handle those cases in my shard but yea, hard to come up with *all* the use cases on your own
<FromGitter> <Blacksmoke16> as thats a good point of wanting to include something on serialization only thats not really part of the object
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5c634a3f80df6804a1944dd1]
<FromGitter> <Blacksmoke16> would prob be a better solution
<FromGitter> <Blacksmoke16> (which works, `on_to_json` is actually a thing)
<FromGitter> <dscottboggs_gitlab> oh, I like that one
<FromGitter> <Blacksmoke16> which would be doable with `JSON::Serializable` atm, nothing there is specific to `CrSerializer` anymore
<FromGitter> <dscottboggs_gitlab> wait so if you `include JSON::Serializable` then you can use the `on_to_json` method? Nice!
<FromGitter> <codenoid> hi
<FromGitter> <Blacksmoke16> @dscottboggs_gitlab yes
<FromGitter> <Blacksmoke16> there is also `def after_initialize` which runs after `from_*`
mps has joined #crystal-lang
<FromGitter> <codenoid> cool
<FromGitter> <j8r> mps i thought about you when reading https://news.ycombinator.com/item?id=19146767
<FromGitter> <j8r> Forth has also the same black color as Crystal https://github.com/urlysses/1991
<FromGitter> <dscottboggs_gitlab> @j8r that's nuts haha
<FromGitter> <j8r> Crystal is nice, but in my opinion it would be better to be simpler – even less similar ways to do the same thing
<FromGitter> <dscottboggs_gitlab> I'm curious, @j8r, what is your favorite?
<mps> j8r: thanks, forth is quite fine to see problem you have from different angle
<mps> I have Alpine apk of the gnu-forth to play sometimes with it, and not sure should I post it to Alpine public aports
jemc has quit [Ping timeout: 250 seconds]