What callback to use in CakePHP to catch all changes to model? - cakephp

I want to add a new functionality to my application: executing a action every time a specific column is changed inside of a specific modal. This column is changed in many places in the application via several methods (save(), saveAll(), updateAll(), saveField()).
My first approach was to use the beforeSave/afterSave callbacks to handle this for every change on Modal level. However, I noticed that these callbacks aren't being done with updateAll() and saveField().
Is there a easy way to track all changes made to a specific column for a specific modal, regardless of the method being used in modal?

You can create your own callback and use it with save all, as described here

Related

Prevent AngularJS from dirty checking several thousand rows each $digest cycle

I have a data source that could potentially be several thousand rows. I want users to be able to scroll through the list and filter it without performance problems. My data source automatically fires an event whenever a record changes.
Currently this data is mapped to $rootScope.datasource.
I would like to be able to isolate this large data set from the rest of Angular's $digest cycle and prevent Angular from dirty checking several thousand rows every time something unrelated happens elsewhere in my app. I want Angular to only $digest datasource when I tell it to (after one of my change events fires.)
I've looked at libraries like Bindonce and Watch Fighters. This is a great option if the data is totally static, but my records are going to change occasionally, and I want the UI to update when I tell it to.
Is this currently possible in Angular?
You shouldn't watch large dataset. Instead, watch single value which describes dataset state.
That single value could be incremental counter or hash of you data. If that value changed, watcher listener function will be called.
Another option -- deregistrate watcher after first use and register it if dataset changed.
Also you should try not to use watcher and use $broadcast with updated state.
You could use bindonce and force an update of the UI when you know there were changes. To trigger this update you need to recompile the template. I've done this in this plunker by 'abusing' ng-include, but you could write a special directive that does just that.

What is the cakePHP way of checking if a user is allowed to perform an action on a particular item?

Working with cakePHP this is my situation:
I have Users and Orders. Orders are created by Users. Only the user that created the Order is allowed to edit it. (admins can also, but I don't think that is important).
I am using the standard Auth component and have an isAuthorized function in my OrdersController that checks if the user is logged in and stops users from performing actions that they are not allowed to perform.
I want to make a decision on whether or not the user can perform the action based on the params passed and the data that comes out of the database. i.e. does the user own the order they are trying to edit? I am currently checking inside each action if this is the case.
Is there a way that I can trigger the same workflow that is triggered by returning false from isAuthorized? maybe throwing an Exception?
I don't want to do these finer checks inside the isAuthorized function, because it will require ugly methods of accessing the passed params, and duplication of data retrieval. How does cakePHP expect me to handle this?
(I have more complicated checks to make in other controllers)
This is what you're looking for:
http://book.cakephp.org/2.0/en/tutorials-and-examples/blog-auth-example/auth.html#authorization-who-s-allowed-to-access-what
overriding the AppController’s isAuthorized() call and internally
checking if the parent class is already authorizing the user. If he isn’t, then just allow him to access the add action, and conditionally access
edit and delete.
Hope this helps
There are a few ways to get this to work. I have a simple example outlined here:
http://nuts-and-bolts-of-cakephp.com/2009/04/22/simplistic-example-of-row-level-access-control-with-auth-security-and-app-model-in-cakephp/
It should give you an idea of how to handle this in general, and then you can build on top of that as one approach.

ExtJS4 - Store per panel instance?

I'm really new to the MVC pattern in Ext.
I have a tabpanel with multiple instances of the same component (let's call it product), each should call the server when it's opened, with an id parameter.
Right now, in order to create these tabs - I use this in the Product controller
Which creates a new instance of a view, but I feel like it's really incorrect.
createMainView: function (opts) {
return Ext.widget("productDisplay", opts);
}
I call it from my "main" controller, like this:
var tab = this.application.getController("Products")
.createMainView({ productId : id, closable: true })
tabs.add(tab);
tabs.setActiveTab(tab);
What's the correct way to properly use multiple instances of a view, each having an instance of one store and behavior (via the controller).
Can I use one named store for them (with a js file under app/store/product.js)?
Should I manually call load on the store from the controller (to pass the productId), or is there a nicer way?
It's kind of very broad and interesting question which require big and thorough explanation (which you can find btw on the Sencha.com in their guides and manuals). I would like highlight couple points so you have something to start with:
Stores are usually global objects. You don't keep two instances of one store in general. You can use filtering (local or remote) if you need to present information from the that store in several different views. The only time you would need to clone store is if you want to present different information from that store in 2+ different views at the same time.
Controllers are usually spawned by main application object. You don't have to do anything special - just list them in the controllers: [] property. And then spawed when application is launched (before their views are created and rendered). Keep that in mind.
If you have modal view - it's ok to create it manually and either re-use it or destroy and re-create later. You can add filtering and loading to controller which creates these views. And you can re-use same view/controller objects for different tabs if you want.
If your views are presenting one instance of an object (like one product is displayed on each tab) - don't attach stores to those views. Just pass them individual model (record).
I would recommend creating the stores that relate only to that view instance inside of the view's initComponent method.
Your controller's control handlers should be coded in a way that they can differentiate which view dispatched the event. This should not be too difficult because almost all view events contain a reference to the component which fired the event. You could then use the relative query selectors, e.g.: myEventFiringComponent.up('anotherComponent') or myEventFiringComponent.down('anotherComponent') to get a handle on a different component in the same view if you need to.
Please see this post for a full explanation.

How do I track my parent find function call in beforeFind() for CakePHP

I am currently using CakePHP beforeFind() to filter my search queries based on the current logged in user. It seems great at the moment and everything is working smoothly, the only problem is that I need to know where the find function was initially called so that I can apply different query filters based on the parent find function call; is there anyway to achieve that?
That seems like coupling your models to your controllers/actions, which in general is a bad idea.
Try creating a custom method in your model instead. You can have whatever method signature you need, and just call find from within and return its results as needed.

How to get the model and action name of the calling action

I have a log feature in my project that tracks all changes to a couple of different models. Say, whenever a user or an admin edits an account. Or when a user creates a new record. All those actions get recorded in the log table.
I would like to have the log model retrieve the model name and action name by itself in a beforeSave action when called to save a new record. I call it now from a controller action making the save like this:
$this->Log->save(array(
'user'=>$this->Auth->user('id'),
'model'=>$this->name,
'action'=>$this->action));
I would love to be able to shorten it down to:
$this->Log->save();
I found alkerman's wonderful LogableBehavior and it is working like a charm. No need to reinvent the wheel.
I think I'd be inclined to either write a method on app_controller such as
saveLog()
which calls
$this->Log->save($uma_array)
or simplify your existing construct by doing
$this->Log->save($this)
and untangling the data inside the method.
EDIT:
Of course, the best way to do this would be to use observable behaviour using teknoid's pattern: http://nuts-and-bolts-of-cakephp.com/2009/08/10/observer-pattern-the-cakephp-way/
It's not that difficult to implement.

Resources