Ruby on Rails
Tuesday, August 19, 2014
I would recommend you start by getting all that domain logic out of the Controllers and into context or composite objects. Check out http://en.wikipedia.org/wiki/Data,_context_and_interaction or James Coplien's excellent book "Lean Architecture" in which he discusses DCI at length.
This doesn't actually solve the specific Rails-doesn't-reload-associations problem you're having, and in fact I've worked on an e-commerce codebase with the exact same problem you describe. We had several @order.reload calls because of the way Rails is implemented.
Moving to a DCI pattern doesn't eliminate the Rails problem here, but it encapsulates the business logic into a single context object whose responsibility is to both do the operations and then tell the object to reload correctly, producing the expected results. You can test the context object independently of the controller, which is ideal.
I actually think there is significant performance gain from not reloading associations in general, and in e-commerce specific apps you simply need to know this about Rails and suck it up and do @order.reload when you make certain operations. Once you realize this is just how Rails works, and you move that domain logic into a place more appropriate than the controller, it starts to bother you less that you have to do it in the first place.
Just my two ¢
-Jason
On Aug 18, 2014, at 8:15 PM, Phil <phil@edgedesign.us> wrote:
On Monday, August 18, 2014 1:57:08 AM UTC-7, Frederick Cheung wrote:
On Monday, August 18, 2014 2:57:05 AM UTC+1, Phil wrote:Is there a way to turn this sort of caching off globally? (Other caching is fine, I don't want to turn all caching off.)
BTW- It is a bit mind blowing that this is turned on by default. Possible data corruption shouldn't ever be preferred by default over (possible) speed gains. I'd still categorize this as a serious bug, at least as a configuration default.
Not that I know of. As of rails 4 (or is it 3.2?) the generated association accessors are defined in a module (rather than directly on the class so it's easy enough to override them so you could doclass TestParenthas_many :test_childrendef test_childen(force_reload=true) super(force_reload)endendTo change it for all associations without having to do this on a per association basis would probably require some monkey patching inside the activerecord code - sounds brittle.As tamouse says if you use build/create on the association then you won't see this behaviour, although there can still be differences between the array thus constructed in memory and the array you'd get if you had selected from the database (for example if you have an order clause on the association, custom select etc.)
Ah, yes, I see it now in activerecord-4.0.8/lib/active_record/associations/collection_association.rb
OK, makes sense. I've love to have that be a config option I could throw in the environments config files to turn that off, if needed.Rails has been like this at least since the 1.0 days - I can't say I've ever run into particular issues from it.
In my case it was rather nasty. It went something like this:
@order = Order.new ...
... record line items..
@order.line_items... calculate subtotal to calculate tax and record that as the final line item
run charge on credit card, render receipt page, send mailers, etc.
The result was the customer got receipt page/emails and charged without tax! Fulfillment and Accounting pulling up the order would confusingly get the right total and tax.
Thanks, I have a much better understanding of what's going on now.
Phil--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/319cce88-0041-4a95-9062-1e0cdd80373d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment