Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix for broken model.Model#remove by foreign key #379

Closed
wants to merge 1 commit into from

4 participants

@efdi

Try something like:

geddy.model.Post.remove({userId: this.id})

It will break with

/usr/local/lib/node_modules/geddy/node_modules/model/lib/query/query.js:184
          datatype = descr.datatype;
                          ^
TypeError: Cannot read property 'datatype' of undefined

Tracking this down I've found that in geddy/lib/app/index.js there's a hook on 'beforeRemove' event that changes query conditions object adding 'model' and 'event' attributes in there.
The patch is just a simple workaround for this problem.
Not sure of the best way to fix.

@larzconwell

Actually in the docs .remove doesn't take queries, only an ID so maybe that has something to do with it?

@efdi

Well, you're probably right. I didn't even consider this.
It's not clear from documentation how to get a db connection to execute raw SQL. And I couldn't get it reading sources.
The only solution left is to async.each(idsCollection, Model.remove)?

It turns out almost every feature of 'model' I'm trying to use is broken or incomplete.
For example, try to use eager loading for fields with non-default names. It will break.
Eager loading for more than one level of associations is not supported.
Define 'bindings': {model: 'UserBinding'} and you will get 'getbindings' and 'addbinding' methods in model (note casing in names).
I understand that I should report more issues for this. But good report takes time that I don't have after hunting for so many bugs.
Guys, you SHOULD use unit testing. It really helps.

@ben-ng
Owner
@efdi

ben-ng, It would be two calls actually. Get IDs + delete.

@efdi

ben-ng,
your solution is not working in geddy/model + postgresql environment.
Callback after #remove gets this error:

{ [error: syntax error at or near ")"]
  length: 83,
  name: 'error',
  severity: 'ERROR',
  code: '42601',
  detail: undefined,
  hint: undefined,
  position: '67',
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  file: 'scan.l',
  line: '1001',
  routine: 'scanner_yyerror' }

I've tried both: Model.remove(idsArray) and Model.remove({id: idsArray})

@mde
Owner

Sorry it's taken so long to have a look at this. There seem to be a lot of separate issues here. It looks like from your patch that the breakage happens only in the realtime code. Is that correct?

We do have both unit and integration tests, although we don't have as much coverage as we'd like. There's a shared integration test for removing by an ID, or an array of IDs, and they pass in Postgres.

As far as the other issues:

-- What does "eager loading for fields with non-default names" mean? Are you talking about named associations?
-- Eager loading multiple levels of association -- I've opened an issue: geddy/model#66
-- I don't understand what you mean by "define 'bindings'" -- are you talking about adding an association for a model definition?

@efdi

It looks like from your patch that the breakage happens only in the realtime code. Is that correct?

I'm not sure of what you mean. If "realtime code" == "code executed on client" then no it's a server side controller action code.

There's a shared integration test for removing by an ID, or an array of IDs, and they pass in Postgres.

Well when I was elaborating on this bug It was clear from the source code that it would break.
I've ended up using async.each(ids, geddy.model.myModel.remove). Did not try reproduce it since.

What does "eager loading for fields with non-default names" mean? Are you talking about named associations?

It turned out that bug occurs when you try to use associations with compund class names, e.g:

Server = ->
  hasMany "DbConfigs"

geddy.model.Server.first {includes: "dbConfigs"}, (err, server) =>
   console.log server.dbConfigs #=> undefined

geddy.model.Server.first {includes: "db_configs"}, (err, server) => # snake case
   console.log server.db_configs #=> actual array of configs, snake case only as well

I don't understand what you mean by "define 'bindings'"

User = ->
  hasMany 'bindings', model: 'UserBinding'

geddy.model.User.first {}, (err, user) =>
  user.addBinding geddy.model.UserBinding.create(blah: "blah") #=> addBinding is not a function

geddy.model.User.first {}, (err, user) =>
  user.addbinding geddy.model.UserBinding.create(blah: "blah") #=> OK

Thanks for your response!

@mde
Owner

All right, so I've pushed a Geddy update that fixes that problem of reference pollution in app/index.js. This is on NPM, v0.8.12. Let me know if this fixes your problem removing associated items by their foreign key.

For future reference, the remove method in the Postgres adapter simply uses the same query transformation as it does for find and update, so you can remove by id, array or ids, or any query criteria you want: https://github.com/mde/model/blob/master/lib/adapters/sql/postgres.js#L266

The problem with the 'includes' query condition has an (already fixed) issue here: geddy/model#68

I'm going to have to dig a little more on the issue you're having with 'addBinding' -- we have tests that cover this (using 'addProfile'), and they work correctly.

@mde
Owner
mde commented

Your problem with your 'Binding' association is that you lowercased the name in the hasMany call. The current code expected a model definition name (i.e., the constructor). I've updated the code to normalize this better. Fix is in 15c506dcf2ff200c6edeae082213247929a6a765.

@mde mde closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 4, 2013
  1. @efdi

    model#remove by foreign key fix

    efdi authored
This page is out of date. Refresh to see the latest.
Showing with 14 additions and 5 deletions.
  1. +14 −5 lib/app/index.js
View
19 lib/app/index.js
@@ -164,17 +164,26 @@ var App = function () {
event = event.replace('before','').toLowerCase();
+ var _data;
+
if (typeof data == 'object') {
- data.model = model;
- data.event = event;
- id = data.id;
+ _data = {};
+ for (var k in data) {
+ if (data.hasOwnProperty(k)) {
+ _data[k] = data[k];
+ }
+ }
+ _data.model = model;
+ _data.event = event;
+ id = _data.id;
}
else {
+ _data = data;
id = data;
}
- geddy.io.sockets.emit(model+':'+event, data);
- geddy.io.sockets.emit(model+':'+event+':'+id, data);
+ geddy.io.sockets.emit(model+':'+event, _data);
+ geddy.io.sockets.emit(model+':'+event+':'+id, _data);
});
}
Something went wrong with that request. Please try again.