I have something like this on my application controller.
def selected_position
#position = params[:position] if params and params.has_key?(:position)
end
Even with that validation, the value get lost accross the controllers calls. I don't want to use session for this, so there's any solution to keep that value? Thanks!
A solution is to store the position on client side. Maybe local storage is a good option. But be aware that the data can be changed or leaked.
HTTP is stateless by design and so, Rails controllers. The only way to store that between controller calls (a.k.a. sessions) is to store data on client side - session, cookies (or local storage), or server side - database, memory, file, ect.
Related
Somehow it seems like it might be a bad idea, but wondering if it recommended or not when you are using session scope in a controller to store session data in controller fields, say for example, as a kind of caching for user data so you have don't have to keep hitting the db to get frequently requested information for a particular user?
And, by the way, just wondering how long the server holds on to the controller instance in that case. If someone leaves the browser tab open for a week, not using it, does the controller instance for that session hang around indefinitely consuming resources on the server?
You could, use a controller like that, but why not just simply use a cache instead? There are lots of really good caches out there (Spring cache for instance) which will likely be more extensible than this approach.
Session management (and when they expire) is handled by your application container (e.g. Tomcat, JBoss, Websphere, etc.). In most cases without interaction with the server (e.g. hitting a URL or page) they expire after a default of 20 minutes. So once a session expires, the session scoped controller instance becomes a candidate for being cleaned up and removed.
I'm working under rails and, as a beginner, I am trying to understand how the session feature works.
I put my sessions under active record, but when I do this:
#request = Facebook::Request.parse_signed_request(params[:signed_request],
Settings.facebook.app_secret)
puts session
#admin = Admin.find_by_fb_userid(#request["user_id"])
session[#request["user_id"]] = #admin ? #admin : nil
My session continue to display:
{}
Thanks for your help !
How session works?
HTTP is a stateless protocol.It means that it treats each request as an independent transaction
that is unrelated to any previous request so that the communication consists of independent
pairs of requests and responses.
A stateless protocol does not require the server to retain session
information or status about each communications partner for the duration of multiple requests.
The protocol provides no means of storing a user's data between requests.
Therefore, we use Sessions, which allows us to chain multiple requests together into a conversation between client and server, so temporaly keep data.
Session is a hash, so you can add a data into session like to regular hash:
For example, to add a new order into the session can look like this:
e.g. OrdersController
def new
#order = current_user.orders.create # creates a new order for current_user
session[:order] = #order.to_params # adds order information to the session.
end
Sessions can store any kind of string data, but best served by keeping it as small as possible for both speed and security,as third party users can easily decode what information is stored in sessions.
UPDATE
by default session data are stored as cookies but Rails allows to configure session storage in database using ActiveRecordStore or inmemory storage with Redis and Redis store. Each approach has its advantages and disadvantages.
Try printing the session value instead of whole session object:
puts session[#request['user_id']]
Do this before and after setting a session. And make sure you cleanup the session before testing this in browser (clear cookies or start incognito session).
And last but not least, it a bad idea to store whole objects in session. This way you are storing way more data in the session than needed. Try storing just the object id (in your case #admin.id) and then load it whenever needed.
Ok my fault was that I was working on a facebook app I guess and for every refresh, the session is reset by the peer.
But when I continued in my process, everything instantly worked.
And even if session is a stateless protocol, it is used, through the storage that is used to keep the session active all along the session.
Like in PHP or every single language
I've seen some explanations of these, but nothing that really compares where they start, end, or overlap, or good examples of their use.
What is the life span of each of the following data collections? And am I missing any?
Application
Session
ViewData
TempData
application: as long as your application is running. your application may be automatically shutdown and restarted by the server for various reasons
session: as long as the user is actively using your site. this is generally determined by cookies that ASP.NET sends down to give each user a unique ID that expires after a while. there are lots of ways to customize & tweak this to meet various needs
viewdata: as long as the current request is being processed. this is used for sending data from a controller to a view for immediate rendering and thus not persisted
tempdata: until the value is read back out OR until the end of processing the next request in the session OR when the session ends/expires - whichever is sooner. this is meant to be used for moving data from one controller to another when you are issuing a Redirect
Application : This get initiated at the time when an application start and end when the application stops the execution.If user leaves the application domain or application gets restarted then also the application based data is lost.
Session : This is application based storage. This ends when user leaves the current request or the session get expired. It can be stored in several modes like application cookie or client side cookie.
ViewBag & ViewData : This storage method hold the data for the current request. It transport the data between view and controller.
TempData : Lifespan of this storage type depends on, at which request the Tempdata is read. Once it is read by program it gets destroyed. But we can increase its lifespan using peek or keep methods.
on each controller call i have a code that gets some user properties from a webservice. I want to cache these for each user so i only hit the webservice once.
what is the best way to cache code in a controller method so it will allow me to avoid hitting the database on every URL request but also not cache one users info when another user logs on?
You could use the ASP.NET session to store per user values.
Check out the caching piece of the Enterprise library. We use it at work to cache lookups, so you only hit our WCF services once, instead of thousands of times for the exact same data.
You can also use Session, which I highly advise against unless your user is very small.
if (Session("user") == null)
{
Session("user") = CallWebService.GetUser(userId);
}
Why you should keep Session small, for this webpage:
Avoid storing too much data in session variables, and make sure your session timeout is reasonable. This can use a significant amount of server memory. Keep in mind that data stored in session variables can hang out long after the user closes the browser. Too many session variables can bring the server on its knees.
I think I might be misunderstanding something about Rails sessions, so please bear with me, I might not be phrasing my question the best way.
I'm working on an iPhone app with a Ruby on Rails backend. I have a web view which by default goes to the index action of one controller (and uses sessions), and in the background a bunch of API calls going to a different controller (and which don't need to use sessions).
The problem is, the sessions set by my web view seem to be overwitten by the API calls. My staging server is pretty slow, so there's lots of time for the requests to overlap each other - what I see in the logs is basically this:
Request A (first controller) starts. Session is empty.
Request B (second controller) starts. Session is empty.
Request A finishes. Request A has done authentication, and stored the user ID in the session. Session contains user ID.
Request B finishes. Session is empty.
Request C starts. Session is empty - not what I want.
Now, the strange thing is that request B should NOT be writing anything to the session.
I do have before and after filters which READ from the session - things like:
user = User.find_by_id(session[:id])
or
logger.debug session.inspect
and if I remove all of those, then everything works as expected - session contents get set by request A, and they're still there when request C starts.
So. I think I'm missing something about how sessions work. Why would reading from the session overwrite it? Should I be accessing it some other way? Am I completely on the wrong track and the problem is elsewhere?
Thank you for any insights!
This is the result of a race condition caused by how rails handles session. See http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/
It seems like you can't have concurrent requests modifying session reliable. The solution is to use a different method of storing session (e.g. active_record or redis) or you could eliminate the concurrent requests.
Your sessions are maybe cookie based. If that's the case then each of request is starting with the same cookie(session). The cookie holds the session content. Try switching the storage to be on the server. But I in your case with the authentication I think it would be much better to not do this async.
Request A (first controller) starts. Session is empty.
Request B (second controller) starts. Session is empty.
Request A finishes. Request A has done authentication, and stored the user ID in the session. Session contains user ID
.....AND returning the session content in a cookie.
Request B finishes. Session is empty.
THIS one is setting blank session.
Request C starts. Session is empty - not what I want.
Thats because B has set reset the session
It's possible this is because you are storing the user id as ":id" in the session object. :id may be a reserved key in the object. Try using a different name such as session[:user_id].
Good luck!