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> 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
<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>
<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> 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>
<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>
<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