How to maintain state in rails? - ruby-on-rails

It is kind of a multi-step form. I need to bring back the user to the step he's left off the previous time. There is no user login.
I'm stuck with "whether it is possible to maintain user details without login?!".
Can anyone please tell me what would be the best way to do it in rails?!
TIA!

There are 2 ways of going about it. You can either store the half-filled form on your server or you can store the half-filled form on the user's browser in LocalStorage.
1) Server Method
When the user clicks next step you can have an AJAX call send the data to server. Your server can store this in a table and return the id back to the browser. Store this id in browser's LocalStorage or in cookies.
When the user comes to your form next time, check if your id is present in your choice of storage, if yes then fetch the data from server and move the user to next step of the form.
You might need to think about security implications in this method as well. If a user can figure out you are storing ids and get the fetch URL of half-filled form, they can iterate over them and fetch other user's form as well. So you might store something other than id and still use this approach.
2) LocalStorage method
Everything is same as the previous approach but we are not using server to store the form. Simply use browser to store the form and fetch when the user comes on the website later. LocalStorage is a persistent storage so it'll also be available when the user re-opens their browser.
I hope this clears your problem here.

Wicked is ruby gem that is used to make step wizard forms. I think it should help you.

Related

Making sure only one user is editing a form in Rails application

Currently, I have a Rails application whose edit form is on a separate edit page. Is there a way to make sure no two users are accessing the edit page at the same time? Or a user can only access the edit page if no other user is currently on the page?
Or to ask a simpler question, is there a way to get a list of users currently on the page?
I am on Rails 4.
HTTP is a stateless protocol. It was designed to allow idempotent transactions. The server does not store transaction state information about each chain of requests. The session allows you to mitigate this design pattern and allow the server to track where your users have been. In order for you to know if a user is on a page, you will need to store in your database where each user is. Remember, that when a user decides to navigate away from a page, your servers will not know it, only when a request is made to a different page.
I assume you don't need to track anonymous session information, so you probably need to override your controller action that ensures users are logged in to save where the user is at. Before rendering the page, ensure the count of user's current location equal to the rendered page is 0.
You can have AJAX fire on the page, updating the location of your user on these pages so you can ensure that there has been no user in a reasonable timeout. Without the AJAX you would need to consider what the reasonable amount of time a user would be editing information, and consider that a non-reasonable amount of time is likely the actual amount.
There's no 'RAILS' feature that can be turned on to check where a user is located, this would be a roll your own situation.
I think the best way is to use a Redis Store (or anything in memory), or make a temporary sessions table for that.
Then you can authorize the show action to check whatever you want.

In Rails 3, how can I save user search history to the database with no membership/authentication system?

Currently, the site is storing "previously viewed items" via cookies.
I need to take that a step further and not only store those items in the database, but save the user's most recent search, so that they can retrieve the search later by returning to the site (the cookie can handle this), but also through say a four-letter code and later a QR code.
When you get into writing these non-authenticated users' data to the database, what is the identifier to use as the key to differentiate them? And would it be ideal to create the actual model record upon visiting the home page, or perhaps after the initial search?
You could save the IP address, other than that, there is really no way to save something specific to a user.
Use the rails request object. You can access the IP with request.remote_ip.
This is the only thing I can think of that is request specific without auth.

How do I see real-time activity of my users in Rails 3?

What I would like to do is have my admin user be able to see - in real time (via some AJAX/jQuery niceness) - what my user's are doing.
How do I go about doing that ?
I assume it has something to do with session activity - and I have started saving the session to the db, rather than the cookie.
But generally speaking, how do I take that info and parse it in real time ?
I looked at my session table and aside from the ids (id and session_id), I see a 'data' field. That data field stores a hash - which I can't make any sense of (looks like an md5 hash).
How would I use that to see that User A just clicked on Link B, and right after that User B clicked on link A, etc. ?
Is there a gem - aside from rackamole - that might be able to help me?
You might want to check out Mixpanel. They are easy to setup and have some of what you are asking for.
The session data only contains the values stored in the session[]-hash from the user. It doesn't store which action/controller was called, so you don't know which "link was clicked".
Get the activity of your users:
Besides rackamole you have two options IMHO.
Use a before_filter in your ApplicationController to store the relevant info you are interested in. (Name of controller, action or URI, additional parameters and id of the logged in user for example).
Use an AJAX-call at the bottom of each page which posts back the info you are interested in (URI, id of logged in user, etc.) to your server. This allows faster response times from the server, as the info is stored after the page has already been delivered. Plus, you don't have to use a Rails-request to store it. The AJAX-request could also be calling a simple PHP-script writing the data to disk. This is much faster.
Storing this activity:
Store this data/info either in the database or in a logfile. The database will give your more flexibility like showing all actions from one user, or all visitors for one page, etc. The logfile solution will give you better performance.
Realtime vs. Oldschool:
As for pulling out your collected data in realtime, you have to build your own solution. To do this elegantly (without querying your server once a second to look if new data has arrived) you'll need another server process. Search for AJAX Push for more info.
Depending on your application I'd ask myself if realtime notifications for this are really necessary (because of all the hassles of setting this up).
To monitor the activity on your site, it should be enough to have a page listing the latest actions and manually refresh it (or refresh it automatically every ten seconds).
Maybe you can test https://github.com/raid5/acts_as_scribe#readme
It works with Rails 3 too.

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 store user preferences? Cookie becomes bigger

My application (Asp.Net MVC) has great interaction with the user interface (jQuery/js). For example, setting various searches charts, moving the gadgets on the screen and more .. I of course want to keep all data for each user. So that data will be available from any page in the Dumaine and the user will accepts his preferences.
Now I keep all data in a cookie because it did not seem logical asynchronous access to the server each time the user changes something and thet happens a lot.When the user logout from the application I save the cookie to the database.
The Q is how to save the settings back to the db - from the client to the server.
because the are a lot of interactin that I want to record.
example scanrios: closing widget,moving widget,resizing menues, ordering columens..
I want to record that actions. if I will fire ajax saving rutine for each action
ןt will be too cumbersome. Maybe I have no choice..
Maybe I should run an asynchronous saving all of a certain interval seconds.
The problem is the cookie becomes very large. The thought that this huge cookie is attached to each server request makes me feel that my attitude is wrong.
Another problem cookies have size limit. It varies from your browser but I definitely have been close to the border - my cookie easily become 4kb
Is there another solution?
Without knowing your code, have you considered storing the users preferences in a/your database. A UserPreference table with columns for various settings is a possibility.
You could update it via AJAX/JSON if you had a 'Save Preferences' option, or just update it on postback.
EDIT 1: After thinking about it, I think having an explicit 'save preferences' button would be beneficial and practical.
Somewhere on your page, where the use edits the things that generate the cookie, put an button called save, then hook up a jQuery click handler. On click, build a CSV string or another method of storing the preferences for posting back to the server, then use $.post to send it back to an action method in a controller.
Once there, store it in the database somehow (up to you exactly how), then return a JSON array with a success attribute, to denote whether the preference storing was successful.
When the page is loading, get the preferences out of the database and perform you manipulation.
Another solution would be to store the user preferences into the session and write some server side logic (like action filter) that would write those preferences as JSON encoded string on each page (in a script tag towards the end of the markup) making them available to client scripts.

Resources