Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defining relationship between tables #18

Closed
alaibe opened this issue Dec 31, 2014 · 11 comments
Closed

Defining relationship between tables #18

alaibe opened this issue Dec 31, 2014 · 11 comments

Comments

@alaibe
Copy link

alaibe commented Dec 31, 2014

Hi,

It might be stupid but I can't succeed to define association (not embeded) using the perpetuity-postgres gem.
Here is my mappers:

Perpetuity.generate_mapper_for Customer::User do                                                                                                         
   attribute :name, type: String
   attribute :email, type: String
   attribute :api_key, type: String
   attribute :accounts
   index :api_key                                                                                                                                             end                                                                                                                                                      
Perpetuity.generate_mapper_for Customer::Account do                                                                                                      
  attribute :oauth_token, type: String                                                                                                                   
  attribute :provider, type: String                                                                                                                      

  index :oauth_token                                                                                                                                     
end 

If I inspect the db I can see a field with type json for accounts instead of seeing a second table.
Any Idea?

Thx

@jgaskins
Copy link
Owner

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 … ;-)

@alaibe
Copy link
Author

alaibe commented Jan 1, 2015

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?

@jgaskins
Copy link
Owner

jgaskins commented Jan 1, 2015

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

@jgaskins
Copy link
Owner

jgaskins commented Jan 2, 2015

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?

@alaibe
Copy link
Author

alaibe commented Jan 2, 2015

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

@jgaskins
Copy link
Owner

jgaskins commented Jan 2, 2015

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.

@alaibe
Copy link
Author

alaibe commented Jan 2, 2015

Yes sure, see this gist: https://gist.github.com/alaibe/bbe2c256b92b9dc66955

I just reproduce it. Let me know if it works on your side

@alaibe
Copy link
Author

alaibe commented Jan 2, 2015

You can see at the end of the gist the value of account is nil and there is no Customer::Account table in pg

@jgaskins
Copy link
Owner

jgaskins commented Jan 2, 2015

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.

@jgaskins
Copy link
Owner

jgaskins commented Jan 2, 2015

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.

@jgaskins
Copy link
Owner

jgaskins commented Jan 4, 2015

Fixed in jgaskins/perpetuity@5a04bdd and released Perpetuity 1.0.1.

@jgaskins jgaskins closed this as completed Jan 4, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants