Rails - Store unique data for each open tab/window - ruby-on-rails

I have an application that has different data sets depending on which company the user has currently selected (dropdown box on sidebar currently used to set a session variable).
My client has expressed a desire to have the ability to work on multiple different data sets from a single browser simultaneously. Hence, sessions no longer cut it.
Googling seems to imply get or post data along with every request is the way, which was my first guess. Is there a better/easier/rails way to achieve this?

You have a few options here, but as you point out, the session system won't work for you since it is global across all instances of the same browser.
The standard approach is to add something to the URL that identifies the context in which to execute. This could be as simple as a prefix like /companyx/users instead of /users where you're fetching the company slug and using that as a scope. Generally you do this by having a controller base class that does this work for you, then inherit from that for all other controllers that will be affected the same way.
Another approach is to move the company identifying component from the URL to the host name. This is common amongst software-as-a-service providers because it makes sharding your application much easier. Instead of myapp.com/companyx/users you'd have companyx.myapp.com/users. This has the advantage of preserving the existing URL structure, and when you have large amounts of data, you can partition your app by customer into different databases without a lot of headache.
The answer you found with tagging all the URLs using a GET token or a POST field is not going to work very well. For one, it's messy, and secondly, a site with every link being a POST is very annoying to work with as it makes navigating with the back-button or forcing a reload troublesome. The reason it has seen use is because out of the box PHP and ASP do not have support routes, so people have had to make do.

You can create a temporary database table, or use a key-value database and store all data you need in it. The uniq key can be used as a window id. Furthermore, you have to add this window id to each link. So you can receive the corresponding data for each browser tab out of the database and store it in the session, object,...
If you have an object, lets say #data, you can store it in the database using Marshal.dump and get it back with Marshal.load.

Related

Rails: working on temporary instance between requests and then commit changes to database

I have already read Rails - How do I temporarily store a rails model instance? and similar questions but I cannot find a successful answer.
Imagine I have the model Customer, which may contain a huge amount of information attached (simple attributes, data in other tables through has_many relation, etc...). I want the application's user to access all data in a single page with a single Save button on it. As the user makes changes in the data (i.e. he changes simple attributes, adds or deletes has_many items,...) I want the application to update the model, but without committing changes to the database. Only when the user clicks on Save, the model must be committed.
For achieving this I need the model to be kept by Rails between HTTP requests. Furthermore, two different users may be changing the model's data at the same time, so these temporary instances should be bound to the Rails session.
Is there any way to achieve this? Is it actually a good idea? And, if not, how can one design a web application in which changes in a model cannot be retained in the browser but in the server until the user wants to commit them?
EDIT
Based on user smallbutton.com's proposal, I wonder if serializing the model instance to a temporary file (whose path would be stored in the session hash), and then reloading it each time a new request arrives, would do the trick. Would it work in all cases? Is there any piece of information that would be lost during serialization/deserialization?
As HTTP requests are stateless you need some kind of storeage between requests. The session is the easiest way to store data between requests. As for you the session will not be enough because you need it to be accessed by multiple users.
I see two ways to achive your goal:
1) Get some fast external data storage like a key-value server (redis, or anything you prefer http://nosql-database.org/) where you put your objects via serializing/deserializing (eg. JSON).
This may be fast depending on your design choices and data model but this is the harder approach.
2) Just store your Objects in the DB as you would regularly do and get them versioned: (https://github.com/airblade/paper_trail). Then you can just store a timestamp when people hit the save-button and you can always go back to this state. This would be the easier approach i guess but may be a bit slower depending on the size of your data model changes ( but I think it'll do )
EDIT: If you need real-time collaboration between users you should probably have a look at something like Firebase
EDIT2: Anwer to your second question, whether you can put the data into a file:
Sure you can do that. But you would need some kind of locking to prevent data loss if more than one person is editing. You will need that aswell if you go for 1) but tools like redis already include locks to achive your goal (eg. redis-semaphore). Depending on your data you may need to build some logic for merging different changes of different users.
3) Another aproach that came to my mind would be doing all editing with Javascript and save it in one db-transaction. This would go well with synchronization tools like firebase (or your own synchronization via Rails streaming API)

Hold a data object temporarily in MVC controller,MVC,MVC Controller temp storage

I have a object that i want to store for a moment. The object is in a controller for now, the controller will generate a view. A AJAX request is made from the view to next controller. For that moment i need the object previously stored. Previously, i used session and it worked well. But not sure it is the right thing to do. Is session the answer for this or is there anything else?
I have used cache also.but as per the cache concept.It will access for all the users.So one user data will be override to another.So the cached object data will be change for the same user.I need to handle the data storage for an particular user(Independent).
How is it possible? anyother approach is there please share me.
In Controller I have used Httpcontext.cache["key"]=dataset;
but some one suggested like this.but its not displaying
Explain:
In Controller: httpcontext.current.cache is not coming.
HttpContext.Currenthandler and HttpContext.Currentnotification properties only coming.So How can we handle the temp data storage in MVC.
Please help me.
You could use TempData if you want to store data for the next request only. If data should be accessible between multiple requests, then use Session. Here is short explanation of each one with examples.
As Alex said you could use TempData but if you want to use the data in multiple request, you could use TempData.Keep("YourKey") after reading the value to retain the data for the next request too. For your Information TempData internally uses Session to store your data (temporarily)
I would recommend URL parameters for a HTTP Get, or hidden form fields for a HTTP Post, if this is short lived. This is highly about avoiding the session.
But if it should really persist, then a database might be a reasonable location. Imagine a shopping cart that you don't want to dump just because a session timed out; because you'd like to remind the user next time about items they still haven't purchased.
Why not use the session? I don't generally recommend using the session, as you could find yourself with a global variable that two different browser windows are manipulating. Imagine a glass. One window is trying to fill it with Ice Tea. Another window is trying to fill it with Lemonade. But what do you have? Is it Lemonade? Is it Ice Tea? Or is it an Arnold-Palmer? If you try to put too much stuff on the session, and overly expect it to just be there, you might create an application that is non-deterministic if heaven forbid a user opens a second window or tab, and switches back and forth between the windows.
I'm more ok with Temp Data, if you truly have no other options. But this is not for persisting data for more than a second. Temp data will disappear after the first request reads it, as in, it's meant for a very temporary usage.
I personally only use TempData if I have to do a redirect where I can't otherwise keep it with me, or if I need to have that data for say generating a PDF or image that is going to be called via a HTTP Get by a viewer on the actual page, and then only if the model data is too large for the GET url ( many browsers only support just over 2000 characters, which long description or many fields could fill up.)
But again, pushing items around in hidden form variables, or in url parameters can be safe, because you have no multiple window use conflicts (each carries around its own data for peace of mind.)

Using tags for user-set UX details

I'm using acts_as_taggable_on for tagging items across my system so that they're easily searchable.
Now I have a UX problem: I'm noticing lots of places where users choose certain minor states (for example, closing a one-time help box or moving to the next javascript-run step in a given page). We have here situations that are both too minor/numerous/dynamic/fast-changing to be put into a database table (imagine having to migrate with every UX change!), and that there is a need to persist some of these choices beyond the session.
In this case, is there anything wrong with using tags to store these simple decisions? For example, user.set_tags_on(:ui, "closed_index_help") or user.set_tags_on(:ui, "tutorial_1_done"), then showing/hiding these elements in the future by looking at the user's ui_list.
Are there drawbacks to this I'm not considering or is this a prudent way to go?
Another way might be to store the information in the SESSION. You will of course have to migrate the session information to be stored in the DB rather than the cookie, but at least that way - you only have to retrieve the session once.

Storing Product List through out session

Im using MVC ASP.NET C#, jQuery
I'm building what could be decribed as the simpliest shopping cart in the world.
Basically My Clients wants users to be able to browse the site, Click on a product they want and it be added to a "list" and then when they "Checkout" they simply fill in a form and it emails my client with the list of products they had chosen!
I was thinking of something like storing them in a cookie. So as the user browses they won't be lost, Then have a jQuery dialog appear when they choose to view/checkout their cart. and it can list all products and then they simply fill in a simple form..
Is this the best way to go about it. Its a cheap website and I would like the simplest way to do this? All i guess I would need to sort is the product Id's..
Any ideas of better ways or any opinions at all!
Using Session depends on whether you think the users will pick the products in one go. Or will they leave the page and come back in an hour? The problem being that if they come back in an hour, the Session State may have been garbage collected to free up resources on the server, or the session might have expired.
To get around this, if all the products are on one page, you could store the chosen products in a hidden field, encrypted and all, that will stay there until the user closes the app.
You just need to serialize the list of product Ids, pass that serialized string to the view and put it in a hidden field.
Another option would be to store it in the users session. A benefit of this is if the user has cookies turned off and the site caters for cookieless session state then they will still be able to select products and checkout.
The thing to look out for is how much you could potentially end up storing in session. From the sounds of it this will not be an issue but if this could potentially use up an unacceptable amount of memory then you would probably need to consider a database approach anyway rather than cookies.
I'd say to go for the Session object. You can always configure the location of Sessions at runtime
I think some may dislike this storage method (it breaks testing isolation, if i'm not mistaken), but it's there for free :)
If you're using jquery, you could store the basket as a json array inside the $('body').data() element (or actually as i do, under a div called '#storage'). this works as a fantastic local storage mechanism, tho' would only be relevant to the current page that the user was on and would be cleared on moving to subsequent 'new pages' unless of course, your design was such that the shopping page was ALWAYS the same page and only refreshed by ajax methods. this way, you could continually append/modify the json structure on the 'worksurface' page.
i use this technique for a different application of the logic, but virtually for the same reason.
here's a snippet of the kind of thing i do:
/* example of data params key*/
var keyParams = "Data-Search-type-" + $('#searchtype').val();
/* add json to body with key*/
$('#storage').data(keyParams, jsonData);
/* get same data back later */
var jsonData = $('#storage').data(keyParams);
When i 'save' the data to the server, i then clear the data() element back to null. There is of course the other option of localstorage itself which can be used well, especially in disconnected environments (such as mobile apps).
another way to skin the many skinned cat!!

How to pass context around in a ASP.NET MVC web app

Ok, I'm a newbie to ASP.NET web apps... and web apps in general. I'm just doing a bit of a play app for an internal tool at work.
given this tutorial...
http://www.asp.net/learn/mvc-videos/video-395.aspx
The example basically has a global tasklist.
So if I wanted to do the same thing, but now I want to maintain tasks for projects. So I now select a project and I get the task list for that project. How do I keep the context of what project I have selected as I interact with the tasks? Do I encode it into the link somehow? or do you keep it in some kind of session data? or some other way?
As it sounds like you are having multiple projects with a number of tasks each, it would be best practise to let the project be set in the URL. This would require a route such as "/projects/{project}/tasks". It follows the RESTful URL principle (i.e. the URL describes the content).
Using session state will not work if a user possibly have different projects open in multiple browser windows. Let's say I am logging into your system and a selecting two projects opening in two tabs. First the session is set to the project of the first opened tab, but as soon the second tab has loaded, the session will be overwritten to this project. If I then do anything in the first tab, it will be recorded for the second project.
I use:
Session state for state that should last for multiple requests, e.g. when using wizards. I'd be careful not to put too much data here though as it can lead to scalability problems.
TempData for scenarios where you only want the state to be available for the next request (e.g. when you are redirecting to another action and you want that action to have access to the state, but you don't want it to hang around after that)
Hidden form fields [input type="hidden"] for state that pertains to the form data and that I want the the controller to know about, but I don't want that data displayed. Also can be used to push state to the client so as not to overburden server resources.
ok, From what I can tell, the best option seems to be to save it into the Session data
RESTful URLs, hidden fields, and session cookies are your friends.

Resources