Closed alaibe closed 9 years ago
It sounds like you might be expecting the model to load the accounts
data automatically. I haven't built lazy-loading into Perpetuity because, as convenient as it is, it's also the source of some of the worst performance problems. :-)
You'll need to explicitly load the associated data you need. I wrote up a quick example using your mappers. The important part is line 57, where we eager-load the accounts for the retrieved user. The great thing about this is that we can pass in either a single object or an array and it will load all of the accounts for all of the users in a single query. It's kind of like ActiveRecord's includes
method, but a lot more performant on the Ruby side.
I need to improve (or, in a lot of ways, write any) documentation for this. If only it were as fun as talking about the project … ;-)
Indeed your gist is working well (of course). I don't know what I am doing wrong my code is 'similar to yours' but I have only one table. At least I know it is working so the issue is on my side (of course again :) )
Thanks a lot for the help. However I have one more question, is it possible to change the name of the table in the mapper. Instead of having a table Customer::User, I would like a table User. But I want to keep my entity under the namespace Customer. Is it possible?
Yep. There's a mapper DSL method for that called collection
:
Perpetuity.generate_mapper_for Customer::User do
collection 'User'
attribute :name, type: String
# etc...
end
I totally forgot to respond to the thing about only having one table. Can you show me the code where you're inserting the objects into the DB?
I think the problem was because my entity was using virtus. By removing it, it creates a second table as expected.
Awesome for the collection
DSL.
On my side everything is working very well now
Hmm, Virtus shouldn't break it — I've tried to ensure compatibility between the two libraries. Can you post your models as you had them with Virtus and show how you were instantiating them so I can see if I can reproduce the behavior? I just want to make sure it's not a bug in the serializer, and if it's a bug in Virtus we can let solnic know.
Yes sure, see this gist: https://gist.github.com/alaibe/bbe2c256b92b9dc66955
I just reproduce it. Let me know if it works on your side
You can see at the end of the gist the value of account is nil and there is no Customer::Account table in pg
It looks like it's got something to do with the attribute :id
DSL method in Virtus. Changing that to attr_reader :id
makes it work. I usually use attr_reader
for ids because they're not meant to be mutable, but this makes me wonder if there is an actual bug hiding inside Perpetuity.
Perpetuity automatically assigns the id based on what the DB adapter returns as a result of its insert
call. For perpetuity-postgres
, that's a String
(it uses UUIDs by default). You've got it marked as an Integer
, but it doesn't seem like Virtus is trying to coerce it because changing the Virtus type to String
doesn't work, either.
Found it. This is indeed a Perpetuity bug. The mapper relies on @id
not existing (not just it being nil
, but not being defined at all yet) until after the object has been inserted into the DB. However, since @id
is actually defined, the mapper thinks it's been persisted and it doesn't try to insert it, which is why you're not getting your second DB table.
Fixed in jgaskins/perpetuity@5a04bdd940563be323125bd0b4dfe3d8e286287f and released Perpetuity 1.0.1.
Hi,
It might be stupid but I can't succeed to define association (not embeded) using the perpetuity-postgres gem. Here is my mappers:
If I inspect the db I can see a field with type json for accounts instead of seeing a second table. Any Idea?
Thx