Rails 3: Ensure before_save callback is called after others - ruby

Is there a way to ensure that a given before_save callback is executed after all other before_save callbacks in ActiveRecord short of actually ordering them so in the code?
I'm writing an external library that includes some before_save functionality but in order to be effective it really needs to be called after all others. I can get around it but it involves giving up dirty attributes which I really don't want to!
-- edit --
I didn't realise in this that dirty attributes are maintained after the save of the model. So #page.attribute_was will still work after the yield in an around_save.

You could make the callback you want executed last an around_save callback. Check out the list of available callbacks and see if you can simply use a different callback "bucket" for some of your callbacks to ensure they are executed in the desired order.
If you still end up with multiple before_save callbacks and need one to trigger last, you may want to create custom callbacks, like maybe define_model_callbacks :split_save, registering your regular before_save callbacks as before_split_save callbacks, the one you want executed last as a after_split_save callback, and then just a single before_save callback that runs those two groups of callbacks (run_callbacks :split_save). See ActiveModel::Callbacks for more on how to do this.

So this was to get around giving up dirty attributes by using ordered before_<type> callbacks instead of after_<type> callbacks, since dirty attributes changes get wiped after saving.
It turns out, however, that the changes are still accessible in after_<type> callbacks.
I only worked this out after trawling through Vestal Versions code to see how they did it.
Facepalm.
I'm accepting Carl's answer because it's a pretty complete answer to the rather badly presented question.

Related

How do i 'destroy all' a given Resource type in redux-saga?

I'm new to Redux-Saga, so please assume very shaky foundational knowledge.
In Redux, I am able to define an action and a subsequent reducer to handle that action. In my reducer, i can do just about whatever i want, such as 'delete all' of a specific state tree node, eg.
switch action.type
...
case 'DESTROY_ALL_ORDERS'
return {
...state,
orders: []
}
However, it seems to me (after reading the docs), that reducers are defined by Saga, and you have access to them in the form of certain given CRUD verb prefixes with invocation post fixes. E.g.
fetchStart, destroyStart
My instinct is to use destroyStart, but the method accepts a model instance, not a collection, i.e. it only can destroy a given resource instance (in my case, one Order).
TL;DR
Is there a destroyStart equivalent for a group of records at once?
If not, is there a way i can add custom behavior to the Saga created reducers?
What have a missed? Feel free to be as mean as you want, I have no idea what i'm doing but when you are done roasting me do me a favor and point me in the right direction.
EDIT:
To clarify, I'm not trying to delete records from my database. I only want to clear the Redux store of all 'Order' Records.
Two key bit's of knowledge were gained here.
My team is using a library called redux-api-resources which to some extent I was conflating with Saga. This library was created by a former employee, and adds about as much complexity as it removes. I would not recommend it. DestroyStart is provided by this library, and not specifically related to Saga. However the answer for anyone using this library (redux-api-resources) is no, there is no bulk destroy action.
Reducers are created by Saga, as pointed out in the above comments by #Chad S.. The mistake in my thinking was that I believed I should somehow crack open this reducer and fill it with complex logic. The 'Saga' way to do this is to put logic in your generator function, which is where you (can) define your control flow. I make no claim that this is best practice, only that this is how I managed to get my code working.
I know very little about Saga and Redux in general, so please take these answers with a grain of salt.

How to check whether an instance of an ActiveRecord model is up to date?

For testing reasons, I want to check that one of my methods doesn't update a specific entry in my database. Is there a simple way to ask an instance of an ActiveRecord model if its in sync with the database? for instance, if we had a method foobar? that could do this:
old_post = Post.find(1)
updated_post = Post.find(1)
updated_post.update_attributes(name: "this is a new name not like the old name")
old_post.foobar? #should return true, as its attributes are no longer up to date
updated_post.foobar? #should return false, as its attributes match the database directly
So is there a method that acts like foobar, or something like it? Thanks in advance.
I think your problem lies beyond finding a method which tells you wether an attribute has been updated, but in the relationship among the different objects that are instantiated. First it is important to understand, that old_post and updated_post are unrelated ruby objects. They know about how to save their own state to the database, but they do not know about each other.
Therefore your first requirement for foobar? cannot be fulfilled, as old_post will think it is up-to-date as long as no attribute has been updated. In contrast the changed? method will roughly answer in the way you are trying to achieve for updated_post. However it does so because it thinks nothing has happened since it was last saved, this will not be verified against the database upon each call of changed? as this would be wasting a database call in 99.9% of all cases.
This means it is all too easy to generate anomalies between the objects you created as there is no direct connection between the two (except the implicit connection that they once represented the same database row). If you change an attribute in one object (using e.g. title='?' it will change the value of the object and take note of the change in the changed-array. Once you save this object it will save its changed attributes to the database (by creating an individually constructed update-statement).
Another object that is already instantiated (as old_post in your example) will not know about this change and might change other attributes if you are not careful (or even the same ones if they have been changed again). Depending on your database adapter you may try to use the lock! method which will synchronize your object with the database before allowing any modifications. This however will not happen automatically as in most controller methods updates do not conflict nearly often enough to merit the synchronization as it will be idempotent in most cases.
This does not go without saying that rails can not save you from thinking about your transaction semantics if you want to guarantee specific ACID semantics for your controller methods.

Any Good Sendfriend Event Dispatch in Magento?

Looking for a decent observer of the Mage_Sendfriend module, when the product is sent to a friend. I just traced it and don't see anything immediately useful. There is one dispatch written in the module, which actually fires when the send to friend form is loaded, not when it's actually submitted.
Looking at the events triggered, here are some events you might use:
controller_action_postdispatch_sendfriend_product_sendmail
controller_action_postdispatch_sendfriend
controller_action_postdispatch
And in the function you want to use for this event:
$controller = $observer->getControllerAction();
... your code here
You might have to resort to observing the model_save_after and model_save_before events, then checking $observer->getEvent()->getObject() to see if it's the Mage_Sendfriend model you're looking for.
An ugly solution, but sometimes the events just don't line up to solve a problem nicely.
Good luck! Let us know if you find anything good!
Edit: I would also suggest against observing a controller for this, though, since that isn't very modular. If a third-party module provides another interface for the Sendfriend feature, it wouldn't work with your module if you observe controller actions.
You can dispatch custom events when and where you want.
Mage::dispatchEvent('any_name_for_your_custom_event',
array('key'=>$value,'key'=>$value,'key'=>$value)); //can pass how many values you want in this array.
And in your config you just make your nodes to look for this event, and call one method from observer.
Its simple.

Rails 3 observers and current_user

There is few similar questions on Stackoverflow about getting of current_user form Rails 3 observers, but basic ideas the same:
1) passing of current_user via
attr_accessor :current_user
in the model we need to observe.
But this unacceptable for me, as, i need to observer 10 models (create, update, delete actions), and i don't want to pass this on each action, for each controller.
2) Storing current user in Thread. Completely unacceptable.
So what is the best practice? And, let's say, i want to get not only current_user in my observer, but also, IP address?
Any ideas?
After investigating for more, i found it's totally useless to use Rails native observers in a such a tasks. Because, if you need to pass something from controllers, in my case it was current_user, this totally ruins observer's beauty.
So my answer to my own question is: still stuck with something like acts_as_audited
My suggestion would be to add a last_modification_by field to your model. In your observer you could then use that to figure out who made the change and who gets the notification.
Then have your view/controller code put the current user in that field.
This seems to me to be the safest approach. I'd worry about the observer using the current user - it feels to me that the current user should be divorced from the quasi background-processing that the observer is doing. (Which is why stashing the current user in a Thread - which I've used in the past with great success - feels wrong here also).
This approach (having a last_modified_by also lets you make modifications to records in batch - perhaps sending email to the owner of the record that, "The system has updated your record because (some daily processing routine happened). last_modified_by some created user which represents the system (or admin user).

Ruby: slow down evaluation

I'm interested in simply slowing down the evaluation of ruby code. Of course I know about using sleep(), but that does not solve my problem.
Rather, I want to slow down every single object instantiation and destruction that happens in the VM.
Why? So I can learn about how particular procedures in ruby work by watching them being carried out. I recently learned about ObjectSpace and the ability to see/inspect all the objects currently living in a Ruby VM. It seems that building a simple realtime display of the objects and properties of those objects within the ObjectSpace and then slowing down the evaluation would achieve this.
I realize there may be ways of viewing in realtime more detailed logs of what is happening inside the ruby process, including many procedures that are implemented at low-level, below the level of actual ruby code. But I think simply seeing the creation and destruction of objects and their properties in realtime would be more edifying and easier to follow.
You could be interested in the answer to this question: getting in-out from ruby methods
With small edits to the code reported there, you could add a sleep to each method call and follow the code execution.
If you want to output some information every time an object is instantiated, you could do that by overriding Class#new. Here's an example:
class Class
alias old_new new
def new(*args)
puts "Creating: #{self.inspect}"
sleep 0.1
old_new(*args)
end
end
class Point
end
class Circle
end
The alias old_new new line creates a backup new method, so we can have the old behaviour. Then, we override the new method and put some code to inspect the subject class and sleep for just a bit for the sake of better readability. Now, if you invoke Point.new, you'll see "Creating: Point". Circle.new will display a "Creating: Circle" and so on. Any objects that are created will be logged, or at least their classes, with a small delay.
The example is a modified version of the one from here.
As for destruction of objects, I'm not sure if there's a sensible way to do it. You could try to override some method in the GC module, but garbage collection is only initiated when it's necessary (as far as I'm aware), so you could easily play with ruby for a while without it ever happening. It probably wouldn't be very useful anyway.
I think the problem is not that ruby is too fast.
In your case you should use some software architecture, for example Model-View-Controller.
It could be in this way. In View you can show options at which speed the Controller should show information for you or you're able to slow down or increase the speed of showing information. Then Controller evaluate small steps (calling methods in Model) and rendered the results of evaluation in the View.
The View is not always the browser or window application, it could be also just a simple terminal.

Resources