
Grokking Diesel, Rust's ORM - fanf2
https://medium.com/@Buys/grokking-diesel-652cb8886a63
======
kbenson
_The last major component, and ‘secret weapon’ or ‘unofficial guide’
(according to me) is the the test suite in the official repo
([https://github.com/diesel-
rs/diesel/tree/master/diesel_tests](https://github.com/diesel-
rs/diesel/tree/master/diesel_tests))._

The tests are indeed informative, and give a good idea of how it would be used
in practice. I just looked at a few and I have a _much_ better idea of how
Diesel looks to be used in practice.

What I didn't see, and don't know if it exists since I haven't read a lot of
the docs, is whether Diesel has a built in way to deliver joined results as
HashMaps with all fields, as that would be the simplest way I would use it in
practice.

For example, if I'm doing the equivalent of:

    
    
        SELECT user.*, post.*, comment.* FROM user LEFT JOIN post ON user.id = post.user_id LEFT JOIN comment ON post.id = comment.post_id
    

Does it have a helper method to identify the three tables that are joined, and
instead of returning individual rows, return a HashMap of the user_id to user,
a HashMap of the user_id to a list of posts, and a HashMap of the post_id to a
list of comments? I think that would be:

    
    
        vec![ HashMap<i32,User>, HashMap<i32,Vec<Post>>, HashMap<i32,Vec<Comment>> ]
    

This would approximate the actual "objectiness" or many ORMs, and would make
it easier to loop over data in the desired way with a minimum of boilerplate.

Edit: Or perhaps the more performant way would be to allow registering of
callbacks for each change of user, post and comment, and call the appropriate
one if defined. That way there isn't time and memory spent on condensing the
data into hashmaps? I'm new to thinking about how to deal with ORM results in
a language like this.

~~~
rabidferret
Not a HashMap specifically, but there is a way to group them into `Vec<(User,
Vec<(Post, Vec<Comment>)>)>`. (Which you can convert into a hashmap pretty
easily)
[http://docs.diesel.rs/diesel/associations/index.html](http://docs.diesel.rs/diesel/associations/index.html)
for details.

~~~
kbenson
That's actually what I was looking for. I'm was too out of practice in general
with signatures in static languages and unfamiliar with Rust's syntax in
specific to figure it out and express what I was looking for correctly. ;)

------
neverminder
I wish it was closer to Scala's Slick which is an FRM (Functional Relational
Mapping), since Rust's syntax is so similar to Scala. Unlike ORMs, libraries
like Slick or JOOQ (Java) have pretty much 1 to 1 DSL to SQL and Slick also
provides compile time type safety which in my opinion is the main point of
using it.

~~~
steveklabnik
Hm, Diesel is also trying to do the "1-1" thing and is _certainly_ focused on
compile-time type safety.

I haven't used Slick, I'd be interested, if you have the time, in an
elaboration with examples on this stuff.

~~~
neverminder
Well, like I said Slick is not an ORM whereas Diesel is. Slick is not as much
about an ORM abstraction, but writing SQL queries in Scala by leveraging it's
collections library, taking advantage of Scala's advanced features such as
operator overloading, etc.

For instance this is an example from Diesel:

Post::belonging_to(user).load(&connection)

And this is how it would look like in Slick:

Post.filter(_.userID === 1).result

So both of the above would translate into SQL "SELECT * FROM posts WHERE
user_id = 1", however Slick is more explicit whereas Diesel definitely feels
like an ORM. The tripple equals in Slick example for instance is a nice touch
and an example of operator overloading, because userID could be of type
Integer or Option[Integer] (nullable field) and it would work both ways.

~~~
steveklabnik
> like I said Slick is not an ORM whereas Diesel is.

I personally find "ORM" to be such a broad term as to be almost meaningless.
This may be a personal problem :)

I see now. I am pretty sure that you could write

    
    
      posts.filter(user_id.eq(1)).load(&connection)
    

if you wanted; the belonging_to is just fancier and a bit shorter.

Anyway, thank you! I've mentally filed a "check out Slick sometime" bug for my
infinite personal-to-do list :)

~~~
neverminder
No problem, I guess what I'm trying to say is that just like Rust took
inspiration from Scala syntax (at least I get this feeling), maybe so could
Diesel from Slick.

~~~
rabidferret
Slick was definitely an influence on Diesel's design. I tried to have our
query builder map more closely to SQL though, whereas Slick feels like it's
trying to pretend it's just an Iterable.

------
dvdplm
Is the column limit still a problem for Diesel? The 16 columns max default is
not enough and even the optional 26/52 can be too little for some odd legacy
schemas. I'm curious: is this a limitation that will be overcome as the
library matures or is it intrinsic to the codegen architecture?

~~~
killercup
It's currently dependent on implementing traits for very large tuples, so you
could argue it's a language feature we are waiting for (cf. open RFC #1935
[1]). (There was a PR on Diesel to use HLists but it's no longer pursuit.)

[1]: [https://github.com/rust-lang/rfcs/pull/1935](https://github.com/rust-
lang/rfcs/pull/1935)

~~~
neverminder
What was the reason you guys dropped HList approach? I'm curious since I have
to deal with tables with north of 200 hundred columns and because of forever
annoying Scala's tuple parity limit (22) Slick falls back to HList which is
really heavy on a compiler and IDE aside from other drawbacks.

~~~
rabidferret
We didn't want to commit to our own home-grown hlist type until we had some
indicator of whether the language was going to go with variadics based on
tuples or hlists.

------
steveklabnik
Diesel's authors have been hard at work on docs, but there's only so many
hours in the day. Love to see posts like this.

------
kiliankoe
Completely unrelated to the topic, but does anybody know why I'm getting a
private gist link with the post's content when sharing it from MobileSafari
(iOS 11 Beta)?

------
Scarbutt
I would have though that ORM's were an antipattern in Rust.

~~~
fredsir
How come?

~~~
Scarbutt
Maybe because of the language constructs that facilitate functional
programming, you would think a data driven centric approach would be chose
first over objects.

~~~
steveklabnik
Rust doens't have objects. (Trait objects _kind of_ come close but are very
rare and I've never used one with Diesel.)

I think if you read the post, you'll see that Diesel is very data-driven.

Personally, I tend to call it a "query builder" if I think someone might be
ORM-phobic; I find it closer to that than other ORMs, even though it's
authored by the maintainer of one of the most massively popular ORMs ever.
They've sometimes joked that that experience has taught them what not to do ;)

~~~
gchp
> even though it's authored by the maintainer of one of the most massively
> popular ORMs ever

Just curious, what ORM is that?

~~~
steveklabnik
ActiveRecord. Referencing it is a double-edged sword; Diesel is very much
_not_ ActiveRecord, so by saying it up front, people tend to get the wrong
impression.

~~~
gchp
IThat's cool, didn't realise it was the same author.

I understand. The other side of that coin though I guess is that knowing this
might give some more confidence in using diesel. ActiveRecord was the first
ORM I used, and knowing now that diesel is "from the same stock" (for want of
a better phrase) gives some extra confidence in what it can do / where it is
going.

Not that I was not confident in it before...

~~~
steveklabnik
Yup, absolutely, that's the other side of the sword :)

~~~
dmix
Indeed, the flood of Rails people who went over to Rust have definitely given
some people pause to consider the direction it was taking.

I don't see this particular case of someone who spent a significant amount of
time coding core Rails OSS library being seen as a negative though, quite the
opposite. If anything it would be an excellent measure of the language for
that particular use case assuming any competent developer would seek to
operate in the constraints of the language rather than shoehorning an existing
implementation into something that doesn't fit.

The bigger question is whether the ORM label itself is limiting or can be
understood to fit into a broader scope of implementations.

~~~
rabidferret
I think people read way too much into the ORM label. Diesel is very much a
query builder first, not an ORM. As a random data point, I've been fixing bugs
in Rails lately by basically copying over code from Diesel and converting it
to Ruby. That code has all been in Arel not Active Record.

I agree that the "I make Rails" thing is a double edged sword. I would hope
people would see it as an indicator that I have a lot of experience and
lessons to learn from, but I think many people see the opposite.

~~~
yazaddaruvala
Thoughts on replacing Arel with Diesel + Helix[0]?

[0] [https://github.com/tildeio/helix](https://github.com/tildeio/helix) \-
When Helix can handle that complexity (if it can't already)

------
endymi0n
After the unfortunate news from NPM today, I'm hoping Diesel doesn't come with
a built-in defeat device... /s

