Hey, I've got an element that does a requestAction to grab records sorted by date.
What I haven't been able to workout/find is how to restrict it to only include records who's date is after now.
For example, in my element I something similar to:
$stuff = $this->requestAction('stuff/get_stuff/sort:my_date/direction:asc');
How should I go about restricting it to only records with my_date after now?
Is their another param I should add or is there something I could add into a find(...) call in my get_stuff action in controller stuff?
Advice or a friendly nudge in the right direction would be grateful!
It really depends on whether or not this will ALWAYS be the action you want to take. But here are a couple of ideas.
You can add a condition to the find query: (Complex Find Conditions)
$this->Stuff->find('all', array('condition' => array('Stuff.my_date >' => date('Y-m-d'))));
You can add a beforeFind callback method to the model that implements the same basic process. It will add the condition to every find query for the given model. (beforeFind)
You can create a new method in the controller to find the records you need and just call that, with all the custom parameters in place in the find. Then just ensure that you check it with if($this->params['requested']) to ensure it only comes from your requestAction() call, and return the dataset.
Then ensure that you cache the result, so that you aren't creating a huge overhead on your application by calling a new dispatch cycle every time someone loads the page.
Related
How can I invalidate a single item when working with useInfiniteQuery?
Here is an example that demonstrates what I am trying to accomplish.
Let`s say I have a list of members and each member has a follow button. When I press on to follow button, there is a separate call to the server to mark that the given user is following another user. After this, I have to invalidate the entire infinite query to reflect the state of following for a single member. That means I might have a lot of users loaded in infinite query and I need to re-fetch all the items that were already loaded just to reflect the change for one item.
I know I can change the value in queryClient.setQueryData when follow fetch returns success but without following this with invalidation and fetch of a member, I am basically going out of sync with the server and relying on local data.
Any possible ways to address this issue?
Here is a reference UI photo just in case if it will be helpful.
I think it is not currently possible because react-query has no normalized caching and no underlying schema. So one entry in a list (doesn't matter if it's infinite or not) does not correspond to a detail query in any way.
If you prefix the query-keys with the same string, you can utilize the partial query key matching to invalidate in one go:
['users', 'all']
['users', 1]
['users', 2]
queryClient.invalidateQueries(['users]) will invalidate all three queries.
But yes, it will refetch the whole list, and if you don't want to manually set with setQueryData, I don't see any other way currently.
If you return the whole detail data for one user from your mutation, I don't see why setting it with setQueryData would get you out-of-sync with the backend though. We are doing this a lot :)
What is a general good practice for when some action - changes multiple models in Backbone.js:
Trigger multiple PUT requests for each mode.save()
Single request to sync the entire collection
In case if the quantity of the changed models greater than 1 - definitely it should be the second item.
Usually, good REST api practice seems to suggest that you should update, save, create, delete single instances of persistent elements. In fact, you will find that a Backbone.Collection object does not implement these methods.
Also, if you use a standard URI scheme for your data access point, you will notice that a collection does not have a unique id.
GET /models //to get all items,
GET /models/:id //to read an element,
PUT /models/:id //to update an element,
POST /models/:id //to create an element,
DELETE /models/:id //to delete an element.
If you need to update every model of a collection on the server at once, maybe you need to ask why and there might be some re-thinking of the model structure. Maybe there should be a separate model holding that common information.
As suggested by Bart, you could implement a PATCH method to update only changed attributes of a particular element, thus saving bandwidth.
I like the first option, but I'd recommend you implement a PATCH behavior (only send updated attributes) to keep the requests as small as possible. This method gives you a more native "auto-save" feel like Google Docs. Of course, this all depends on your app and what you are doing.
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.
I have a situation where, in a model's afterSave callback, I'm trying to access data from a distant association (it's a legacy data model with a very wonky association linkage). What I'm finding is that within the callback I can execute a find call on the model, but if I exit right then, the record is never inserted into the database. The lack of a record means that I can't execute a find on the related model using data that was just inserted into the current.
I haven't found any mention of when data is actually committed with respect to when the afterSave callback is engaged. I'm working with legacy code, but I see no indication that we're specifically engaging transactions, so I'm trying to figure out what my options might be.
Thanks.
UPDATE
The gist of the scenario is this: We're taking event registrations, but folks can be wait listed. A user can register (or be registered) for a given Date. After a registration is complete, I need to check the wait list for the existence of a record for the registering user (WaitList.user_id) on the date being registered for (WaitList.date_id). If such a record exists, it can be deleted because it's become an active registration.
The legacy schema puts me in a place where the registration isn't directly tied to a date so I can't get the Date.id easily. Instead, Registration->Registrant->Ticket->Date. Unintuitive, I know, but it is what it is for now. Even better (sarcasm included), we have a view named attendees that rolls all of this info up and from which I would be able to use the newly created Registration->id to return Attendee.date_id. Since the record doesn't exist, it's not available in the view.
Hopefully that provides a little more context.
What's the purpose of the find query inside of your afterSave?
Update
Is it at all possible to properly associate the records? Or are we talking about way too much refactoring for it to be worth it? You could move the check to the controller if it's not possible to modify the associations between the records.
Something like (in psuedo code)
if (save->isSuccessful) {
if (onWaitList) {
// delete record
}
}
It's not best practice, but it will get you around your issue.
i need some help
which is when i on my index.ctp/view.ctp, i need to call to my controller function to perform some task. what code i can use to perform this action?
i need to call to my controller function, which send in a value (user_id) to the function and get me a certain action. how can i do that? i might calling in a javascript function as well.
If you need to call a Controller function from the View, you're doing it wrong. It's not proper MVC.
Having said that, requestAction would be the proper, albeit slowest way to do so. You could hack around a bit more and get an instance of the Controller from the ClassRegistry. But I'd seriously recommend you to restructure your program flow so you don't need to do this to begin with.
You should probably perform the task in the controller before you get the view. But if you need to do some view work on the data you are displaying you might want to consider making a Helper class.
http://book.cakephp.org/view/101/Creating-Helpers
If your task doesn't generate any output - you might want to consider doing it in the controller before you even get to the view stage.
If your task has some form of output - use requestAction with a view Element
http://bakery.cakephp.org/articles/view/creating-reusable-elements-with-requestaction
That link should be a good starting point. There are also good posts by Mark Story on his blog that detail the actual performance of requestAction and it really isn't that bad if you don't abuse it all over the place.
http://mark-story.com/posts/view/how-using-requestaction-increased-performance-on-my-site
http://mark-story.com/nodes/view/reducing-requestaction-use-in-your-cakephp-sites-with-fat-models
If you really need to trigger some sort of logic in a predictable way and that logic might happen in more than one place you can also use an event observer pattern to trigger the controller action you need to run.
http://cakealot.com/2009/04/eventful-a-cakephp-event-system/