Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.Start your free trial
Tyler Fowler20,743 Points
CoffeeScript preserve multiple `this` objects?
=> in CoffeeScript is just calling
apply (can't remember which) at the end of the function and passing the
this object. So not too different. Also I know it's somewhat of a complicated question but Stack Overflow is failing me at the moment.
I'm in a rather unique situation (one I've never found myself in before) and I can't find anything on how it should be handled, so I thought I'd ask here. (and perhaps start a good discussion on how it should be handled)
I'm writing a Node.js/Express application that does a series of database calls in various route handlers. I'm using the node-sqlite3 module to make the database calls. In this case the user is uploading a file, so I take that from the form POST data and save it to the filesystem (will be moved to blob storage later) and generate some xml files for other reasons. The way that I name these files is by the id in the database to facilitate routes like '/file/:id' to GET the file later on, as well as leveraging the database to ensure I don't have name collision issues.
I'm doing this in CoffeeScript so I'm wrapping this model in a
class, so it uses
@) to access these helper methods. Before I was doing a
last_insert_rowid() call to get the id of the thing I just inserted but this opens me up to potential race conditions. So as it turns out when you do an
INSERT in the node-sqlite3 module the callback it calls when it's done saves the last inserted row id in the
this object (so
(err) -> fileid = @.lastID). Now for some code (names changed and simplified).
uploadFile: (fileData, cb) -> @.openConnectionIfClosed() @db.serialize => # preserve the @ object to allow calls to class methods like @.saveFile @db.run 'insert into thing (val=$val)', $val: 'some_val', (err) -> if err cb err return # @ refers to the this object provided by @db.run fileid = @.lastID async.waterfall [ (async_cb) => # uh oh, the @ object is the one from the db library, not my class # earning me a 'method undefined' error @.saveFile fileid, async_cb # etc... you get the idea ... ], (err) -> cb err @.closeConnection()
So I'm needing to retain the class
this object to access instance methods, but I also need to get the
lastID value out of the
this object returned by default from the callback in the db call. Obviously if I change the callback on the db call to fat arrows I can access my class methods, but then the
ctxt = @ at the top of the method but obviously this isn't favorable. Any ideas?
EDIT: Oh, and I forgot to mention, I can't just name the file something else because I also need that id to update the database. The call to
async.waterfall does: Save file -> generate xml metadata file & save it -> add the path of the xml file to the database entry retroactively. Though I could potentially use a statement to do that without completely isolated database calls, haven't investigated that yet.
EDIT #2: Adding a context does work. By this I mean putting
ctxt = @ at the top of the method and where I use
@db down in the call to
async.waterfall replacing it with something like
ctxt.run .... Not very elegant though.