I have a question about paginating non-persisted data which is sourced from a remote http request to an API (or many).
My Rails 3 app sends a net/http request to a search engine API and receives a JSON object. I'm loading this into ruby and paginating the results in the view. The initial query receives 50 hits and Kaminari is displaying:
#items = Kaminari.paginate_array(array).page(params[:page]).per(10)
Now when I click for page 2 in the view, the controller executes the request for the JSON again rather than using the results in array.
This code is in a helper method and that's a problem. I that realise moving the pagination code into the controller will make this possible. bing_search returns #items now.
if params[:bing]
#bing = bing_search(#query)
end
I need something like:
#items = Kaminari.paginate_array(#bing).page(params[:page]).per(10)
I am just wondering how I can persist the array while paginating. I have just looked at caching and that looks promising but I don't know anything about how it works yet.
Related
VueJS + Quasar + Pinia + Axios
Single page application
I have an entity called user with 4 endpoints associated:
GET /users
POST /user
PUT /user/{id}
DELETE /user/{id}
When I load my page I call the GET and I save the response slice of users inside a store (userStore)
Post and Put returns the created/updated user in the body of the response
Is it a good practice to manually update the slice of users in the store after calling one of these endpoints, or is better to call the GET immediatly after ?
If you own the API or can be sure about the behavior of what PUT/POST methods return, you can use local state manipulation. Those endpoints should return the same value as what the GET endpoint returns inside. Otherwise, you might end up with incomplete or wrong data on the local state.
By mutating the state locally without making an extra GET request, the user can immediately see the change in the browser. It will also be kinder to your server and the user's data usage.
However, if creating the resource(user, in this case) was a really common operation accessible by lots of users, then calling the GET endpoint to return a slice would be better since it would have more chance to include the new ones that are created by other users. But, in that case, listening to real-time events(i.e. using WebSockets) would be even better to ensure everyone gets accurate and new data in real-time.
Background:
I'm using DataTables in conjunction with a JS library called "Turbolinks", which basically turns your application into a Single Page Application (SPA) without all the overhead of using a true client-side framework. It is extremely useful for Ruby on Rails application performance.
There's a couple of headaches it introduces though - one is compatibility with DataTables. I've got it working pretty well by basically destroying any DataTable on a Turbolinks navigation, and then re-initializing it on turbolinks page load again. This method works well and seems to be the all-around accepted answer as to the best practice to get DataTables to work with Turbolinks.
Question:
On of the last features / finishing touches I'm trying to add to some of my applications is DataTable state saving. The issue I'm facing is that every time a table is destroyed/re-initialized on a page navigation, the...I'm actually not quite sure what to call it, but it looks like from inspecting the settings object on the stateSaveCallback - it looks like its the sInstance and/or the sTableId:
DataTables_Table_0
Then the localStorage key gets set as:
DataTables_DataTables_Table_0_/current_path: "{data: data}"
where current_path is whatever path/page you're on.
Then when it get re-initialized upon returning to the page, it gets set as DataTables_Table_1, and so on and so forth - so the state never gets correctly loaded.
Is there a way to override that ID (or some way to set the name of it in the stateSaveCallback / stateLoadCallback) so that it doesn't increase the last '0', '1', etc at the end of it? That way when the table is re-initialized, it will pull the saved state from just DataTables_Table/current_path?
The answer is to simply give the table an ID! Then DataTables won't assign it its own ID with the incrementing number and the saveState option just works.
Also, the destroy/re-init actually causes the server to get hit twice in the case of an AJAX table.
The better way to do it is to disable the turbolinks cache for any index pages with datatables. If not, you'll end up doing two requests to the server when only one is needed.
I'm beginner to Lithium framework. Could anyone please help me to understand flow of ajax request in this framework via an simple example. e.g. I'm using jquery and I have to access a method in controller via ajax call and then need to display result in view. Controller function can be called from normal request as well as for ajax request.
Thanks in advance!
Perhaps if you posted a little bit of code, we could show you some code, in return.
By default, Lithium responds to HTML and JSON requests.
Suppose you have an action named index within PostsController, you would, by default, access it via /posts/index which would return HTML.
However, if you access /posts/index.json, you should get json output which you can process via jQuery. Of course, you'd have to comment out media.php in bootstrap.php and I'm also assuming you haven't changed the default routes.
There's a bit of info here as well, if you're interested.
i have an action which will invoke a service (not database)to get some data for display,and i want to do paging on these data.however,every time a second page is clicked,it will invoke this action and of course invoke the service again,actually when i click the first page link,it already generate the whole data including what the second page needs. i just want to invoke the service once and get all the data,and later when paging,i don't need to invoke the service again,how can i deal with that?hope someone could give me a hint~
There are several ways to address this. If it's practical and a limited amount of data, it's ok to return the entire data set in the first request.
If that's your case I would consider returning a pure JSON object when you load the page initially. You can then deserialize this into a JS object variable on the web page that you can perform your paging operations against. This is an example of client side paging where all the data exists client side.
Another approach is to do Ajax based paging where you request the data for the next page as needed. I would still recommend returning JSON in this scenario as well.
The two approaches differ in that the first one returns all the data upfront, whereas the second one only returns what you need to render any given page.
My simplistic understanding of the Rails stack is that it does the following (in general)
The input is a HTTP message (GET, POST, PUT, DELETE, HEAD), a URL, some (optional) cookies, a (optional) session token, and possibly some data packed up in JSON or XML format.
This HTTP message is handled by Rack which may run it through a set of "middleware" functions which add or remove data from the message, and may use the data to add, alter, or remove data from the program's data store.
The HTTP message at the output of Rack is sent to the Rails router, which maps it to a controller, an action, and a params hash with the session information, cookies, and other parameters in it. The data is dispatched to the appropriate controller.
The controller method parses the params, and algorithmically combines it with data from the database (via models), optionally changes data and then dispatches a set of variables starting with # to a view template.
The view template takes the data and merges it with the view template to form a view with the appropriate format (eg. HTML, JS, JSON, XML, etc), or it tells the caller (via a HTTP return code) to redirect to another URL.
What I would like to do with my Rails web application, using the Rails console is
Compose a valid HTTP message with URL, session ids, cookies, and encoded data (JSON or XML).
Inject this data into the Rack interface, and inspect what comes out before it is sent to the Rails router.
I would then like to then send that data to the Rails router and see what comes out before it goes to the controller.
I would then like to send that data to the controller and see what comes out before it is sent to the view template.
And I would then like to take that that data and run it through the view template and have display on STDOUT, or have it automatically open a web browser and see it render.
Are there any existing Rails tools which can do this? If not, can anybody point me to the Rails code where these interfaces occur?
Most of what your looking for is within the actionpack library of rails.
ActionDispatch handles the interface with rack, the middleware and the router. The request hits the router as the last piece of middleware. The router itself gets called within action_dispatch/routing/mapper. So if you want to intercept the request before it hits the router, inject your own piece of middleware before the routes get called.
Once the the router map verifies that it has a valid route it calls the application which is over in the railties library. This I believe then bumps you back over into actionpack into the ActionController middleware. I'm not sure exactly where you'd want to tie in to intercept before getting to the controller, but I'm guessing it would be somewhere around that ActionMiddleware class.
From there your off into actionpack. The render/redirect that your controller calls sets up what will happen within actionpack. I'm not sure exactly where AC calls into AP but you should be able to sift your way through it and find the path your looking for.
As for the response, your back to the middleware. Once rails has the view stitched together it basically unwinds itself and goes back down the middleware stack before sending the response back to Rack.
Hope that helps.