I guess it’s hard to say what the advantages are without testing… Assuming you are already indexing all of your id and *_id database columns and SQL query caching is on, I’m not sure what advantages association caching is actually providing. A test might be to edit collection_association.rb from the gem manually to set force_refresh = true and do some benchmarking (which I’d like to do when I get some time).
If your dataset is small and properly indexed, and you have very few related items, chances are you will see very little change in performance from reloading every time you access the order line items. If you have several hundred line items, things may be a little different. If your database is on a different machine than the web server, things may also be a little different.
Yes, you are probably right(?).
Ironically, 37 Signals has some very good articles on how to do caching properly without worrying about getting stale data, this is a basic example:
Ironically, this has nothing to do with what you are having problems with. You will still have the “stale” object. (Unless you are suggesting that Rails should check the updated_at for every ActiveRecord object every single time you access it. In that case, good luck. I doubt you will ever find any ORM so poorly written.)
No no, I mean there’s already a layer of SQL caching that takes care of repeated identical selects between updates and inserts. Is there not? (I think there is?) Association caching seems unneeded(?) or at least a lot less intelligent than the existing SQL query caching.
I’m not sure what you mean by the ‘rails way’ in this case. Usually the rails way means not having to worry about cache management by default.
I don’t worry about cache management by default. In addition, I don’t have to worry about how to start using the database caching, and when I might need it.
In my case I have a mailer that simply looks like this:
In the view it does @order.line_items and they are sometimes wrong. This just feels like an ugly hack to try to make rails faster during the days when ruby was really, really, slow (thankfully the latest since 2.0.0 is MUCH faster).
If your order line items are wrong, that is because somewhere in the code, somebody made some incorrect assumptions and wrote some incorrect code, examples of which have already been pointed out. Thankfully, the goal of the framework is not to make sure that can never happen by default, with the side effect that you may need to make drastic changes to the code if you ever want to start caching. The framework does provide multiple ways to create related many records in a way that updates the relation in the parent object.
Before blaming ‘incorrect code’ or bad programmers, look back again at my example. It’s quite trivial and reproducible. Saves order line items, in what I would consider a completely sane and logical way, call back line items to compute tax, add the last line item (the tax), and then throws the @order to payment processing, mailers, receipt page… where totals are wrong and tax is missing. I understand that doing things differently avoid the problem and I have used them to fix this issue on my end, but I still am quite skeptical as to how a programmer is supposed to know about these pitfalls.
In your case, you can either find that problem and fix it, or simply force reload the items in the mailer you are working on. To complain about bad code as a “Rails Problem” is not useful. Bad code can be written in any language, using any framework.
Oh, absolutely. I’m not just venting to vent, I have a few (what I think are constructive) questions:
How can one turn off ‘association caching’ (for lack of a better name) without having to edit the .rb file in the gem (the answer appears to be you can’t?)
If not, can we simply add a simple config switch (e.g. config.active_record… that goes in config/environments/*) to Rails to turn this feature off/on easier in the future? (Not just for my sake, I mean as a general improvement.)
If this association caching was added as a hack to improve performance back in the day, is it really still needed? Perhaps it can be removed or turned off by default? Perhaps it was added before SQL caching and it is not needed(???)
To be honest, I have written code that requires a reload where certain functionality is invoked. I have a callback on deleting a related many that modifies a value in the parent. However, that code really should be refactored such that the children are not destroyed directly, but instead a method on the parent should destroy the child.
It would be interesting if has_many and such could throw a callback on the child model(s) to know to update automatically. Again, if this is already handled by the SQL caching layer, perhaps it’s all moot to even have caching at the association layer. It makes sense that Rails can’t know that changes are being make to the database outside of the scope of Rails (e.g. somebody on a SQL console), but it seems like it could be cleaner about knowing what it is doing within its self.
My apologies if I sounded a bit frustrated before. Now that I understand what’s happening and how to avoid the problem, I am back in my zen state. ;’) Thanks again for your previous thoughts and insight.