I should have made this more clear in the episode:
An instance variable only sticks around for a single request, so using the technique described will only benefit you if you need to call a method multiple times per request.
If you need to store a model or other data between requests, look into memcached.
@niko, right. This isn't as necessary in edge rails since the query is cached. However it will return a new instance of User every time so I still recommend caching it in an instance variable.
Ryan, yes, I am in the iTunes Music Store. In my iTunes I see all 1-55 listed except for 20-23. Given you're seeing them all I'm guessing now that I may have inadvertently deleted those from my iTunes (I did already view them once).
So an iTunes question for you or anyone -- is there a good way to restore a deleted iTunes entry?
I've just discovered Railscasts and thought I'd start at the first episode. Low and behold, absolute genius, I cut one of my request times in half by caching the return from my ldap lookup. Thanks, hoping to find many more gems as I work my way through the episodes.
This might sound like stupid question. I recently started learning php with sql. This looks like php coding but am not sure. It maybe little advance for me or maybe am just been stupid and there is previous tutorials.... I looked at #1 because I thouth it would be the easiest to get my head round. I kinda understand what is going on in this tutorial... but I am not sure where I would apply such a method? Thanks Ste
@Ste Just to clarify, this is Ruby on Rails, NOT PHP. They're completely different, so this is probably the wrong place if you're looking for specific copy-and-paste examples (but the concept might still apply, I'm not quite sure).
@Ste You might want to start with the Agile book titled "Agile Web Development with Rails". It makes a very nice beginner course for people who have done web development with other languages and frameworks.
Ryan, spectacular job on the Webcasts. Helps demystify the rails magic. This is a great tip but I am not clear on how it works? I thought instance variables only live as long as the routine is called. So every time you call current_user, isn't @current_user destroyed? Why isn't it? Is that rails or ruby at work? I assume rails.
@mike b, in Ruby, instance variables stick around as long as the object exists. In Rails this controller object sticks around for the entire web request. So if you call current_user multiple times during that one request the User.find call will only happen once.
I have a doubt regarding caching in instance variables, forgive me if it is stupid.
What if I would need to catch more than 500 records..For example if I need to retreive all the employees of an organization..Would it be fine or is there any other suitable way to maximise performance?
I dont know why, but I'm not getting the result I was expecting.
I'm doing a project, when I know that the Id for one object is different in each environment. So the only thing I need is to keep the result of a query in a variable, and use it foreve on.
I forgot to change the development config file (config/environments/development.rb). Here is only needed to change "config.cache_classes = false" to "true".
What if another thread updates your object in the database, while you are working with an old instance of the user? I think it is much better to cache these objects on the database server, or through a data access object. It really depends what your doing with the user, but it can get kind of messy caching stuff in this way.
If you want to push performance further, you can write the user data serialized to the session if session access/data retrieval is faster than db access/data retrieval. Be aware you have to clean (or update) the user data stored in the session if the users data gets modified.
On a side note: will this still be required with rails3? As far as I understood ARel its only executed "when required" does this mean in this case only once?
I'm sorry. I'm still a little unclear. I understand that instance variables of a controller are killed on every request. This is because every new request generates a new controller object (is this correct?). However, wouldn't the instance variables in a model last until model.destroy?
Otherwise, how is the lifetime of a model's instance variables defined?
Instance variables in models are also lost because each request is basically a blank slate.
The only thing to persist through requests are class variables, however, they too get lost when the server is shut down (or in the case of Phusion Passenger, the worker goes idle and gets removed).
To overcome these issues, use an external caching system. Rails has support for a few, like memcached.
It's worth to mention that now this is the default behaviour, as Rails offers query cache, so you don't have to store the result of an expensive query on an instance variable. If your application performs the same query on the same request more than once, Rails automatically returns the result of the first execution, without touching the database twice for the same query.
Additionaly, if you enable identity map, you have the extra benefit of always getting the same object representing a record of your database, instead of creating new objects.
I have been working through the relevant Railscasts, and just for sentimental reasons watched the first one. Thank you for creating such a wonderful resource. You distill such clear practical understanding in an entertaining way.
Hi Ryan,
It seems this code is brittle. At the moment we have a method and an instance variable for accessing to current user data. Data associated with him/her can be corrupted in any other object methods. By the way, what if I assign some value to @current_user before calling current_user method? Right, @current_user would never be filled with data from Data Base.
I agree, caching could be very useful, but we should be as accurate as we can. Caching solution is a synchronization trouble, I guess. So what about to incapsulate data caching in data class?
ruby
classUser < ActiveRecord::Basedefself.find_by_id(id)
# we can hold @last_requested_user variable and compare# given id with @last_requested_user.id and then return# right user... or something like this.endend
Merely User class knows when its data was changed, so caching of some part of data is responsability of User class. One more argument for this solution is that, actually, User class is only point access to data, so we have to incapsulte logic like this in data classes, dont'we?
There is a small issue with the caching mechanism you showed. If the user details is modified by another session , then the cache would not fetch the latest information. In short, there should be a way to invalidate this cache.
I should have made this more clear in the episode:
An instance variable only sticks around for a single request, so using the technique described will only benefit you if you need to call a method multiple times per request.
If you need to store a model or other data between requests, look into memcached.
This is kind of automatically included in edge rails auto query caching.
@niko, right. This isn't as necessary in edge rails since the query is cached. However it will return a new instance of User every time so I still recommend caching it in an instance variable.
@Luke, I went ahead and changed the feed so it will display all episodes. You should be able to download all episodes through iTunes in a day or so.
It appears the feed is missing episodes 20-23. If you can, can you add those to the iTunes feed?
@Brian, hmm, those episodes are showing up for me in iTunes Music Store. Is that where you're looking?
Ryan, yes, I am in the iTunes Music Store. In my iTunes I see all 1-55 listed except for 20-23. Given you're seeing them all I'm guessing now that I may have inadvertently deleted those from my iTunes (I did already view them once).
So an iTunes question for you or anyone -- is there a good way to restore a deleted iTunes entry?
since people are talking about it here...
I'd love all the back issues in iTunes as well. Right now, i'm only seeing episode 33 on. Did the feed get reset to only allow the last 30 episodes?
Thanks for such a great screencast!
@brooke, the full quality feed should show all episodes on iTunes. The iPod version doesn't - I'll try to fix that.
Can anyone explain this in more attractive way, so that I can easily uderstand the actual concept?
agree with saket...
would be great if there is a common scenario that demonstrates the benefit of using this technique...
I've just discovered Railscasts and thought I'd start at the first episode. Low and behold, absolute genius, I cut one of my request times in half by caching the return from my ldap lookup. Thanks, hoping to find many more gems as I work my way through the episodes.
This might sound like stupid question. I recently started learning php with sql. This looks like php coding but am not sure. It maybe little advance for me or maybe am just been stupid and there is previous tutorials.... I looked at #1 because I thouth it would be the easiest to get my head round. I kinda understand what is going on in this tutorial... but I am not sure where I would apply such a method? Thanks Ste
@Ste Just to clarify, this is Ruby on Rails, NOT PHP. They're completely different, so this is probably the wrong place if you're looking for specific copy-and-paste examples (but the concept might still apply, I'm not quite sure).
@Ste You might want to start with the Agile book titled "Agile Web Development with Rails". It makes a very nice beginner course for people who have done web development with other languages and frameworks.
Have a look.
Ryan, spectacular job on the Webcasts. Helps demystify the rails magic. This is a great tip but I am not clear on how it works? I thought instance variables only live as long as the routine is called. So every time you call current_user, isn't @current_user destroyed? Why isn't it? Is that rails or ruby at work? I assume rails.
thanks again for your dedication to the community
@mike b, in Ruby, instance variables stick around as long as the object exists. In Rails this controller object sticks around for the entire web request. So if you call current_user multiple times during that one request the User.find call will only happen once.
good tutorial, i had exactly that problem, with that instance variables it can improve the performance
Shawn, the movie is not damaged, but the url is wrong.
You can get the movie at:
http://media.railscasts.com/videos/001_caching_with_instance_variable.mov
Hi,
I have a doubt regarding caching in instance variables, forgive me if it is stupid.
What if I would need to catch more than 500 records..For example if I need to retreive all the employees of an organization..Would it be fine or is there any other suitable way to maximise performance?
I dont know why, but I'm not getting the result I was expecting.
I'm doing a project, when I know that the Id for one object is different in each environment. So the only thing I need is to keep the result of a query in a variable, and use it foreve on.
As a simple example, I tried to do
<script src="http://gist.github.com/99813.js"></script>
and displaying that on the view, and it has everytime different value.
What is my mistake? should I use memcached instead?
Thanks
Ooops! I tried to paste the following on Gist:
@now ||= Time.now # => or also @@now ||= Time.now
I already know the solution :)
I forgot to change the development config file (config/environments/development.rb). Here is only needed to change "config.cache_classes = false" to "true".
What if another thread updates your object in the database, while you are working with an old instance of the user? I think it is much better to cache these objects on the database server, or through a data access object. It really depends what your doing with the user, but it can get kind of messy caching stuff in this way.
Hello,
I am just (re)starting with Rails.
If you want to push performance further, you can write the user data serialized to the session if session access/data retrieval is faster than db access/data retrieval. Be aware you have to clean (or update) the user data stored in the session if the users data gets modified.
On a side note: will this still be required with rails3? As far as I understood ARel its only executed "when required" does this mean in this case only once?
I'm sorry. I'm still a little unclear. I understand that instance variables of a controller are killed on every request. This is because every new request generates a new controller object (is this correct?). However, wouldn't the instance variables in a model last until model.destroy?
Otherwise, how is the lifetime of a model's instance variables defined?
Instance variables in models are also lost because each request is basically a blank slate.
The only thing to persist through requests are class variables, however, they too get lost when the server is shut down (or in the case of Phusion Passenger, the worker goes idle and gets removed).
To overcome these issues, use an external caching system. Rails has support for a few, like memcached.
In Rails 4.2.5, you don't need to do it. You can see the details here Caching Database Results in Rails 4.2.5
It's worth to mention that now this is the default behaviour, as Rails offers query cache, so you don't have to store the result of an expensive query on an instance variable. If your application performs the same query on the same request more than once, Rails automatically returns the result of the first execution, without touching the database twice for the same query.
Additionaly, if you enable identity map, you have the extra benefit of always getting the same object representing a record of your database, instead of creating new objects.
Just had to give a thumbs up to the first ever episode
Hi Ryan
I have been working through the relevant Railscasts, and just for sentimental reasons watched the first one. Thank you for creating such a wonderful resource. You distill such clear practical understanding in an entertaining way.
Chris
Hi Ryan,
It seems this code is brittle. At the moment we have a method and an instance variable for accessing to current user data. Data associated with him/her can be corrupted in any other object methods. By the way, what if I assign some value to
@current_user
before callingcurrent_user
method? Right,@current_user
would never be filled with data from Data Base.I agree, caching could be very useful, but we should be as accurate as we can. Caching solution is a synchronization trouble, I guess. So what about to incapsulate data caching in data class?
Merely User class knows when its data was changed, so caching of some part of data is responsability of User class. One more argument for this solution is that, actually, User class is only point access to data, so we have to incapsulte logic like this in data classes, dont'we?
Hi Ryan,
There is a small issue with the caching mechanism you showed. If the user details is modified by another session , then the cache would not fetch the latest information. In short, there should be a way to invalidate this cache.
This is also a handy way to show newer devs the power of the or/equals operator. Great cast!
sempak
nice try
Do not do this to awesome forum
What is dealer for?
Good try
Must do caching