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
Elouin has quit [Read error: Connection reset by peer]
Elouin7 has joined #crystal-lang
<FromGitter> <mixflame> you gotta use `password.verify` against the plaintext password
<FromGitter> <mixflame> create a new `Crypto::Bcrypt::Password` from the hash you created
rocx has quit [Ping timeout: 260 seconds]
rocx has joined #crystal-lang
rocx has quit [Ping timeout: 260 seconds]
mistergibson has quit [Quit: Leaving]
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 265 seconds]
zorp has quit [Ping timeout: 240 seconds]
<FromGitter> <Blacksmoke16> @watzon check this out
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f23add2e3160e46ba9547b9]
<FromGitter> <Blacksmoke16> :0
Elouin7 has quit [Quit: So long and thanks for all the fish!]
Elouin has joined #crystal-lang
<FromGitter> <benphelps> there is something wrong with the specs
<FromGitter> <benphelps> if I run a single test using focus: true, it reports that is the only test that runs, but my debug code fires as if it isn't
<FromGitter> <benphelps> if I comment out the rest of the specs, it runs as expected
<FromGitter> <benphelps> so focus: true doesn't actually focus on a single test, it just reports on a single test
<FromGitter> <Blacksmoke16> (highly POC at this point), but key things to note: ⏎ ⏎ 1) notice no ORM related ivars on the `User` object ⏎ 2) `User` object is totally agnostic of a specific db connection AND driver ⏎ 3) property types are mapped behind the scenes to db types, that are also handled in a DB agnostic way, i.e. use `UUID` type on PG but `varchar(36)` on dbs that don't support it ...
<FromGitter> <Blacksmoke16> @benphelps where is your debug code?
<FromGitter> <benphelps> inside a class method that the spec calls
<FromGitter> <benphelps> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f23af678d82e66252f6849f]
<FromGitter> <benphelps> 1 examples, but my lexer was called twice, once from a test that does not have focus: true
<FromGitter> <Blacksmoke16> sure you dont have two/nested focus?
<FromGitter> <benphelps> no
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/9h2k
<FromGitter> <Blacksmoke16> has to be something else going on
<FromGitter> <benphelps> oh yeah, you're right
<FromGitter> <Blacksmoke16> mhm
<FromGitter> <benphelps> now I'm debating the usefulness of this debug shard
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <benphelps> https://github.com/Sija/debug.cr
<FromGitter> <benphelps> pp doesn't print out anything but debug!() does
<FromGitter> <Blacksmoke16> might be running when the block is captured maybe?
<FromGitter> <benphelps> actually, I'm wrong twice, pp does print
<FromGitter> <Blacksmoke16> see if you can make a playground link that reproduces the issue
<FromGitter> <benphelps> reproduces it
<FromGitter> <Blacksmoke16> oh, well yea, that first `pp` isnt in a spec
<FromGitter> <Blacksmoke16> all specs are evaluated then filtered
<FromGitter> <benphelps> even if it is, sorry
<FromGitter> <Blacksmoke16> specs run as part of `at_exist`, so the blocks are called, hence you see your prints, but `it` blocks are captured so they are not executed if they are not focused
<FromGitter> <Blacksmoke16> i.e. dont do stuff outside of a `it`
<FromGitter> <benphelps> but you can focus on any level of the spec
<FromGitter> <benphelps> I'd expect that to mean, it doesn't run if it isn't focused
<FromGitter> <benphelps> only `it` should be focusable if that's the case, right ?
<FromGitter> <Blacksmoke16> doing `focus: true` on a describe focuses all `it` blocks that are within that `describe` block
<FromGitter> <benphelps> so how do I setup data for testing?
<FromGitter> <Blacksmoke16> do it within your `it` blocks
<FromGitter> <benphelps> every time?
<FromGitter> <Blacksmoke16> yes
<FromGitter> <benphelps> unreasonable
<FromGitter> <Blacksmoke16> can make some helper methods to help
<FromGitter> <Blacksmoke16> got a more complete example?
<FromGitter> <benphelps> how does Crystal test it's self, since it'd have to test the Lexer, AST, etc
<FromGitter> <benphelps> I guess that'd be a good place to look
<FromGitter> <Blacksmoke16> if you're used to like rspec the stdlib's version is a lot simpler
<FromGitter> <benphelps> well, it just works much differently in regards to focus
<FromGitter> <Blacksmoke16> https://github.com/icy-arctic-fox/spectator there is this, but imo im not a big fan due to the extra dependency and added complexity for the avg crystal dev
<FromGitter> <benphelps> i don't see why you couldn't filter the tests without calling the block
<FromGitter> <Blacksmoke16> you are, but only the `it` blocks are filtered
<FromGitter> <benphelps> why? that doesn't make sense
<FromGitter> <Blacksmoke16> you would need to evaluate the describe blocks to know if there are any `it` within it
<FromGitter> <Blacksmoke16> because `it` blocks are the only things that are actually executed, `describe `blocks are just namespaces for tests
<FromGitter> <benphelps> that makes sense, I guess that'd be a tradeoff I would be willing to make
<FromGitter> <benphelps> some of my tests have a lot of setup, specific to that single describe block
<FromGitter> <benphelps> most of them, actually
<FromGitter> <Blacksmoke16> sec
<FromGitter> <benphelps> so I'd call that code, for every test
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/9h2w
<FromGitter> <Blacksmoke16> prob is a bit of a smell tho...
<FromGitter> <Blacksmoke16> prob better to have a like `private def new_program : Program` then use that method in your specs versus `program`
<FromGitter> <Blacksmoke16> and maybe a like `def with_tests(input, cases, &)`?
<FromGitter> <benphelps> hmmmm
<FromGitter> <Blacksmoke16> yea, like how they reuse private helper methods within each it block
<FromGitter> <benphelps> i guess if that's how they do it, who am I to argue, haha
<FromGitter> <Blacksmoke16> are shards out there more like rspec or whatever, but meh
<FromGitter> <Blacksmoke16> KISS
<FromGitter> <Blacksmoke16> anyway, im off to bed o/
<FromGitter> <benphelps> since I'm also testing a language
<FromGitter> <benphelps> thanks for the help
_whitelogger has joined #crystal-lang
<FromGitter> <benphelps> `.is_a?` cannot accept a class via variable?
<FromGitter> <benphelps> ```expected = AST::Expression ⏎ if something.is_a?(expected) ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5f23dfcd61a83168462ae75f]
<jhass> right, since it's a pseudo method and actually a compile time assertion, the compiler needs to understand the value
<jhass> (well there's still a runtime assertion, but the compiler restricts the type at compile time in the branch)
<FromGitter> <benphelps> makes sense, thank you
<jhass> expected === something might do what you want, idk
<FromGitter> <benphelps> I need the type guarantee inside the block
<jhass> ah yeah, then it can't be a variable
<FromGitter> <benphelps> i think overloading different functions is a better way to do this, rather than passing the type as an argument and switching inside the method
<jhass> sounds sensible
_whitelogger has joined #crystal-lang
zorp has joined #crystal-lang
<FromGitter> <Blacksmoke16> prob, but as a note `case` would be good for this i think
<FromGitter> <Blacksmoke16> ```case expected ⏎ when SomeType then thing_one ⏎ when OtherType then thing_two ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5f240e5c477381102331f653]
ua is now known as uni
<FromGitter> <dscottboggs_gitlab> @Blacksmoke16 thought you weren't gonna do an ORM?
<FromGitter> <Blacksmoke16> more of a proof of concept at this point
<FromGitter> <dscottboggs_gitlab> fair enough. never really used an ORM so IDK much about them
<FromGitter> <Blacksmoke16> is yet to be seen if it'll actually work and/or ill move forward with it
<FromGitter> <Blacksmoke16> going with a more data mapping approach, versus AR
<FromGitter> <dscottboggs_gitlab> AR?
<FromGitter> <j8r> AR, the 15th
<FromGitter> <Blacksmoke16> active record
<FromGitter> <Blacksmoke16> @dscottboggs_gitlab https://www.thoughtfulcode.com/orm-active-record-vs-data-mapper/
<FromGitter> <dscottboggs_gitlab> I really don't get what the big deal is about just writing the queries by hand
duane has joined #crystal-lang
Human_G33k has joined #crystal-lang
<FromGitter> <Blacksmoke16> mainly portability and abstracts some stuff so that its easier to not write bad SQL
<FromGitter> <Blacksmoke16> plus it makes working with the data a bit easier as you have types and can have method and such on them
HumanGeek has quit [Ping timeout: 260 seconds]
<FromGitter> <j8r> but harder to optimize and debug
<FromGitter> <Blacksmoke16> ideally the ORM would take care of some of those optimizations for you
<FromGitter> <Blacksmoke16> really depends on what you're doing tho, a small app with only a few tables prob doesnt absolutely *need* one, as it grows it becomes more helpful
<FromGitter> <Blacksmoke16> esp if you have data in disparate databases of different types etc
<FromGitter> <Blacksmoke16> https://stitcher.io/blog/new-in-php-8 some neat PHP features coming in `8`
<FromGitter> <Blacksmoke16> finally getting some nice features crystal has ha, attribute syntax would conflict with class vars tho
<FromGitter> <j8r> i think a too big app won't fit by using an ORM though
<FromGitter> <j8r> because it will likely use specifics to the DB, and fine tuning will matter more
<FromGitter> <j8r> But mid sized apps quite fit the ORM niche IMO
<FromGitter> <Blacksmoke16> thats the benefit of the data mapper approach, it'll work regardless of what db you use, but allows using db specific features
<FromGitter> <Blacksmoke16> since you have an extra abstraction layer between your model and the actual database
<FromGitter> <wyhaines> The utility of an ORM varies a lot depending on what one is doing. They absolutely can simplify the code in an application tremendously, which is the main reason to use one. ⏎ ⏎ For very sophisticated queries, they can produce queries that aren't as efficient/optimized as hand-built queries. It's the tradeoff, as with so many things, between the time it takes to write the code, and the efficiency of the
<FromGitter> ... code. Any decent ORM, though, will let you drop down to straight SQL if you need to. ⏎ ⏎ And TBH, it's also sometimes just more efficient to push work right into the database than it is to even bother having it in your application. A year ago I was working with an application that had to query large amounts of data from multip ... [https://gitter.im/crystal-lang/crystal?at=5f243c4a36563560f2b53a7f]
<FromGitter> <Blacksmoke16> and granted you can still use an ORM for 99% of your application, and probably still use hand written SQL for that 1% when its too advanced for it to handle
<Rounin> I had to work on a Spring/Hibernate application once, and it had this annotation that let me input native SQL queries... So I just used that for whatever I did, and left the stuff from before as whatever Hibernate uses
<Rounin> That was a pretty good feature
<Rounin> And by "once", I mean my entire career
mistergibson has joined #crystal-lang
mistergibson has quit [Remote host closed the connection]
<FromGitter> <Blacksmoke16> kinda related, should the last inserted ID be included within the `DB::Connection` object that handled the related exec?
<FromGitter> <Blacksmoke16> atm its exposed on the `ExecResult` obj, but it would be easier to pass around the connection
<FromGitter> <sirikon> ✋ Currently working on a Spring application, and happens the same. Most of the queries are okay, but from time to time you have to throw in some native queries.
<FromGitter> <sirikon> > should the last inserted ID be included within the DB::Connection object that handled the related exec? ⏎ ⏎ is the DB::Connection instance shared within multiple places and parallel executions? because if that's the case, you could read the last inserted ID of another fiber and get some trouble. ⏎ ⏎ I prefer having it in a separate `ExecResult` [https://gitter.
<FromGitter> ... im/crystal-lang/crystal?at=5f24582d36563560f2b58a97]
<FromGitter> <sirikon> But my favorite approach is using something like PostgreSQL's `returning` statement. You do an `insert` and return the inserted ID, which can be read as a regular `select`. That's more powerful imho because you can return any other information, not just a single id (Like, multiple IDs, or ids + other stuff generated on insertion), and you don't need to implement extra concepts in the abstraction, like "returned
<FromGitter> ... IDs". Everything is just querying and returning data.
<FromGitter> <Blacksmoke16> i would think each connection could only execute one statement at a time so should be fine in that regard
<FromGitter> <Blacksmoke16> but yea prob better to not have to worry about that
<FromGitter> <dscottboggs_gitlab> @sirikon I really like that feature -- is PG the only one that has that?
antoszka has quit [Ping timeout: 272 seconds]
antoszka has joined #crystal-lang
<FromGitter> <j8r> @Blacksmoke16 Being agnostic of the DB is nice looking theory, but not working in pratise
<FromGitter> <j8r> Each DB has its own quirks, not mentions NoSQL, NewSQL, SQL-like
<FromGitter> <dscottboggs_gitlab> > NewSQL ⏎ ⏎ what fresh hell is this now?
<FromGitter> <j8r> That's the new sql databases basically
<FromGitter> <j8r> Like ArangoDB, RethinkDB
<FromGitter> <dscottboggs_gitlab> oof
<FromGitter> <Blacksmoke16> > but not working in practise ⏎ ⏎ How you figure? It works fine for doctrine. Just need to have the right abstraction layer in place to handle that stuff
<FromGitter> <j8r> It works for not too advanced stuff I guess
<FromGitter> <Blacksmoke16> have a specific example?
<FromGitter> <Blacksmoke16> like UUID columns?
<FromGitter> <j8r> what DB doctrine supports? ⏎ looks like mainly MySQL
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f2463cab9bc40357bac09ce]
<FromGitter> <j8r> Ha, ok
<FromGitter> <j8r> I mean, some databases has features like that some has not
<FromGitter> <j8r> and of course the won't be MongoDB in it (or maybe now since it supports SQL)
<FromGitter> <Blacksmoke16> way it works is there is an abstract `Platform` type, then each vendor extends that for their own stuff
<FromGitter> <Blacksmoke16> so like by default UUID column would be `varchar(36)`, but postgres overrides that to make it `UUID`
<FromGitter> <Blacksmoke16> ofc there only so much you can do to emulate features for portability
<FromGitter> <j8r> I just want to say, how you design your data model must fit in how the DB works
<FromGitter> <Blacksmoke16> right, isnt that true for even if you're not using an ORM?
<FromGitter> <j8r> yes
<FromGitter> <j8r> So, the ORM usually abstracts the common base among the databases.
<FromGitter> <j8r> So, that depends of the app
<FromGitter> <Blacksmoke16> also depends on what "type" of orm you use, AR design versus data mapping
<FromGitter> <j8r> Sometimes devs wants to leverage all advanced features the DB has to offer (types, etc)
<FromGitter> <Blacksmoke16> AR doesnt have that extra abstraction layer
<FromGitter> <Blacksmoke16> that link i posted earlier gives a good overview of the differences
<FromGitter> <j8r> maybe...
<FromGitter> <j8r> so, what about stored procedures?
<FromGitter> <Blacksmoke16> https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/native-sql.html i haven't used that before tho
<FromGitter> <Blacksmoke16> kinda hurts my brain
<FromGitter> <sirikon> @dscottboggs_gitlab AFAIK, Postgres is the only one with that feature, sadly (at least in the classic, relational, not-newSQL world). In other databases you can just run two queries in the same transaction. In MySQL you can `insert into x values y...` and then `select last_inserted_id()` or something like thatç
<FromGitter> <dscottboggs_gitlab> wow. huh.
<FromGitter> <dscottboggs_gitlab> postgres is great
<FromGitter> <sirikon> There's a school of thought (DDD people mostly) that says that you shouldn't let the database decide any value. IDs should be decided in your app and imposed to the DB. This way you can't have autoincrements, just natural keys or GUIDs.
alexherbo2 has joined #crystal-lang
alexherbo2 has quit [Client Quit]
alexherbo2 has joined #crystal-lang
alexherbo2 has quit [Client Quit]
alexherbo2 has joined #crystal-lang
zorp has quit [Ping timeout: 260 seconds]
alexherbo2 has quit [Ping timeout: 260 seconds]
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<FromGitter> <dscottboggs_gitlab> Is there a way to print the deduced type at compile time? I have a type error that doesn't make sense to me
<FromGitter> <asterite> pass that expression to a method like def foo(x : T)forall T and inside it use macro code to puts T
<FromGitter> <dscottboggs_gitlab> thanks
lanodan has quit [Quit: WeeChat 2.8]
lanodan has joined #crystal-lang