On 12/15/2011 12:20 PM, Michael Bayer wrote:
On Dec 15, 2011, at 11:46 AM, Kent wrote:

I notice no such API events as before_expunge() or after_expunge().
Hopefully without taking much of your time, can you point me in any
direction of how I might go about being notified when an object is
expunged?

Why?

(By the way, I didn't mean "Why didn't you add these?" I meant "Why?, You might ask... well, I'll tell you why...")

If we start adding events like that, it suggests we'd be adding a few dozen 
more hooks for before_/after_ pretty much every operation in the Session, 
essentially decorating every method - before_add(), after_add(), 
before_close(), after_close(), before_expire(), after_expire(), 
before_delete(), after_delete() etc etc right ?     This would greatly clutter 
and clog the Session object and add latency.      They'd also be difficult to 
define as there are cascades which take place - do the event hooks accommodate 
just the call of the method itself or also all the objects reached by a cascade 
?

The existing events are specifically to intercept places in the code that 
otherwise can't be intercepted - that is, deep within a series of steps.    
Intercepting public method calls is just as easily done with custom Session 
subclass, or using wrapper code within your own application.

I didn't know I could specify a subclassed Session class, but I see the "class_" parameter to sessionmaker() now, that might be helpful.

There are certain states a persistent record reaches where further
changes to it are forbidden and it becomes a "historical" record, for
example, for accounting purposes.  For example, consider a closed
order, shipped, paid for, done.  There are times, however, when I want
to re-run calculations on such objects to calculate a delta for
finances, etc.  Suppose a discount were retroactively applied to this
order, such that you want to use existing code to rerun tax
calculations, etc for the closed order and inspect all the changes
without danger of it being persisted to the database.

I am heading down the road of expunging objects that have reached this
"archived, historical" state so that I can still use the object for
all it's calculations and be assured that no changes will be persisted
to the database.  (Another thought I had was using transient objects,
but I think the end result is similar)
why not use a before_flush() extension, or similarly a 
before_insert/before_update/before_delete extension, and simply reject flush() 
calls which include such objects in the list of those to be modified ?    The 
fact is they still represent database data and will work a lot better if they 
have access to their persistent state.

While I like the sound of this idea, it doesn't deal very well with the notion of being able to expunge(order) and have everything under its expunge cascade tree automatically excluded, does it? I would need numerous backrefs to reach the "parent" so I could determine status, and I'd need to implement this for all related classes along the expunge path. I've also found in the past that some situations of referencing an unloaded relationship from within before_update, etc. have caused me grief.

If I head this direction, how do I "reject the flush()" for certain instances?

My concern is that once such an object has been expunged, I don't want
any relationship or code or anything automatically reloading or
refreshing it from the database with session.query().get.
you mean, because that raises an error on a detached , or because the objects 
represent in-memory-only state that should no longer reflect database state ?
A while ago (with your help), I already dealt with loading relationships for transient/expunged based on my use case of always a single session, which made that framework change workable. So the reason for my concern is the latter, because it represents a state in memory only. I admit, leaving the object in the session solves this problem, but creates a new one where I can't easily utilize the expunge cascade. If I leave it in the session, I think it also creates a different problem: that I'd need to worry about a different query overwriting (refreshing) my object with the database contents.
My plan was
to record expunged objects on the session object so I could look them
up during reconstruct_instance() and raise an error if the same record
is being loaded from the database that I've already expunged.
if you are going that approach I would just use a library call within your own app called 
"mark_as_historical()", which does the expunge() and also adds the element to 
the collection in question.   This is functionality in addition to what expunge() does.
I had that thought as well, but it doesn't deal with cascaded expunges. I could subclass session for this in a non public API way. But I'm becoming fond of your idea of leaving the objects in the session as you suggested with before_flush() or _update()... any thoughts on how I could work needing to avoid backrefs for every relationship in the expunge cascade? Are there reasons one need to avoid referencing unloaded relationships from within before_upate()? (I can't recall the exact problem I've had in the past with that at the moment.)

Which does your gut tell you is "safer": the expunged approach or the leave in session but prevent writing changes approach?

Thanks very much!
(For what its worth, I've made appeals to my company on more than one occasion about donating to your project, but with little success so far (I think because we can't afford to pay all our current employees quite yet), but we're growing and we'll get there... I would love to have our company donate to the project, you've always been so helpful. For now, a sincere "thank you" will have to suffice.. sorry.)


--
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to