I have the following query in my application
#categories = Category.joins(:posts).select('distinct categories.*').order('label')
This query gets loaded on every page view since the categories are displayed on every page. This seems messy to me since the list of categories are not getting updated that often. Is there a nifty way to cache just the query? I have tried
Category.cache do
#categories = Category.joins(:posts).select('distinct categories.*').order('label')
end
but I still see the query getting loaded every time from the database in the development log.
In your controller, you can try something like:
#categories = Rails.cache.fetch('categories', :expires_in => 24.hours) { Category.joins(:posts).select('distinct categories.*').order('label') }
Which will only read to see if the following data block 'categories' has been cached and not expired. If expired after 24 hours, will then query the model and write the new record into Rails cache.
For more information, I followed the following guide.
Try it out. I have it working this way. Hope that helps.
You can use fragment caching for the part of your view template that displays the categories. This means that the categories will be served from the cache store and the query will only be executed once until the cache is expired (by using the expire_fragment method).
Fragment Caching Rails Guide
Related
I'm not sure where I have gone wrong here. I trying to keep track of pages our customers are on by updating a field on a custom record. When a page is submitted it updates the field and when the page is loaded it updates the field again. However I am getting CUSTOM_RECORD_COLLISION on some of them (not all). I am using the following code to update the field. I am doing it in a loop but break out after the first record as I only want the latest pagetracker record.
for(key in pagetrackerARR){
var pagetracker = pagetrackerARR[key];
record.load({
type : 'customrecord_pagetracker ',
id : pagetracker .id
}).setValue({
fieldId : 'custrecord_cw_max_page',
value : value
}).save();
break;
}
I thought that if I loaded the record each time, it would not run into these errors as it's the latest version of this record.
If you're updating the field when the page is submitted and then again when the page is loaded, it could be that the record is still being written to during the save/submit when you attempt to write to it again during load. If you really need to handle both situations, try using record.submitFields instead of loading the whole record. You could also do the writing to the record on page load after a delay using setTimeout.
When we cache a partial in rails using cache digests, how does the conditional logic in the partial get handled? Does it cache the full template and later apply the conditionals so that the right json/html can be served to the right user?
Does it cache the full template and later apply the conditionals so
that the right json/html can be served to the right user?
This part of question seems a bit unclear to me, so I'll provide different options based on what "conditionals" could be.
First of all, cache digests do not care about inner conditions based on #variables's state (unless a particular state is mentioned inside of its cache key). Consider the following example:
# users.haml
.welcome_block
- if #user.admin?
%h4 Hello, admin!
- else
%h4 Hello, user!
In case you apply caching to the whole page with cache ['users_haml'], the cache would be generated just once (for the first user with whichever role). Any user who accessed this page later would see the same h4 greeting as the one which has been shown to the first user. The reason here is that digest for string users_haml, proved to cache method, is always the same regardless of any circumstances.
On the other hand, cache #user would provide slightly different behaviour. Each user who opens users.haml page would see proper greeting based on his/her role. The reason for this behaviour is that digest differs for all objects of type User, so cache_digests generates N cached pages for N users.
The last one kind of conditionals which comes to mind is the one based on conditional partials rendering, e.g.:
# users.haml
- cache [#user.month_of_birth]
- if #user.month_of_birth == 'October'
= render 'partial_one'
- else
= render 'partial_two'
So, this one renders correct cached page for users with different months of birth. But what should happen if I change the contents of partial_one? How does cache_digests understand that cache should be invalidated for those who were born in october (based on the conditional statement)?
The answer here is that it doesn't know that at all. The only thing it knows is that users.haml depends on both partial_one and partial_two, so changes to either of these inner partials gonna invalidate ALL the users.haml page caches regardless of users' month of birth.
I want to cache the database content in yii and used that data in Yii drop down list. In the dropdownlist want to load the country names from database. (Have 2 tables user and country). In user form need the drop down list. That selected from country table using cache. Where queries are placed and when we can use the cache result in the user form?
In order to cache the results from a table and then use that in a dropdown you'll need to first set up caching in your config file as described in the Caching Overview of the Definitive Guide. If you wanted to use memCache you could set it up like so;
array(
......
'components'=>array(
......
'cache'=>array(
'class'=>'system.caching.CMemCache',
),
),
);
Yii can use a number of difference caches which are listed in the Caching Overview link above.
You'll then need to make use of Yii's data caching features. You can just do this in your user/_form.php view, for example;
...
echo $form->dropDownList($model,'country_id',CHtml::listData(Country::model()->cache(1000)->findAll(),'id','name'));
...
But the more MVC way would be to do this in your controller, something like so would work;
In your UserController:
...
public function actionUpdate()
{
...
$this->render('update',array(
'model'=>$model,
'countryList=>Country::model()->cache(1000)->findAll();,
);
}
...
In your user/update.php view:
...
echo $this->renderPartial('_form', array('model'=>$model,'countryList'=>$countryList));
...
In your user/_form.php view:
...
echo $form->dropDownList($model,'country_id',CHtml::listData($countryList,'id','name'));
...
The examples above use no dependency for the cache, so the cached values will stay valid until the time (in this case 1000 seconds) expires.
To read more about using a cache dependency, you can read the Cache Dependency section of the Data Caching doc.
[EDIT]
If you need to install memcached, and are using xampp on Windows, this is a great guide to get it working: HOW TO INSTALL MEMCACHED ON XAMPP ON WINDOWS 7
I'm trying to perform a query and find 20 records recently created across multiple models using the sunspot_solr gem. Currently it achieves that no problem, but I wanted to add some extra validations for only one of the models that were being searched.
Currently in my User model it lists all new users that were created, but I only want it to list users who have confirmed their email address. I'm using Devise for user authentication and using active record to find all users who have not been confirmed I would do something along the lines of:
User.where("confirmed_at is null")
Or the reverse to test for the opposite. I tried to integrate this with my solr search as so...
Model
#Unless the user being searched hasn't been confirmed...
searchable :unless=> proc { |user| user.confirmed_at == nil } do
time :created_at
time :confirmed_at
end
Controller
#updates = Sunspot.search(Upload,Help,User) do
without(:confirmed_at, nil)
order_by(:created_at, :desc)
paginate page: 1, per_page: 20
end
However this added condition only eliminated user records created after the condition was added to the model. I'm not completely sure how indexing works, but it seems to be caching old information where the newely added conditions weren't being applied. I can confirm this by creating a new user record and I notice immediately it doesn't get indexed until I validate the email address.
What I've tried:
Stopping and restarting server
Stopping server and attempted to stop and restart solr but this produced a PID could not be found error
After reading up a little more on indexing I confirmed my suspicions and found out that I had to re-index my search. To do this I looked at Sunspot readme and found this line:
bundle exec rake sunspot:solr:reindex
I have a bad habit of trying to make use of technologies before I even understand what they do...
Doing the following routes configuration:
resources :cadeiras do
resources :professores
end
resources :cadeiras do
resources :fichas
end
resources :fichas do
resources :exercicios
end
will generate me 2 different links to the same controller and action, running rake routes ill get something like:
fichas GET /fichas(.:format) {:action=>"index", :controller=>"fichas"}
cadeira_fichas GET /cadeiras/:cadeira_id/fichas(.:format) {:action=>"index", :controller=>"fichas"}
The first action will reference all the 'fichas' while the second on is referencing only 'fichas' from 'cadeiras' how is it possible to distinguish the two actions?
I would like to avoid three level nesting problems as described here :http://weblog.jamisbuck.org/2007/2/5/nesting-resources
Thank you for your time
If I understand your question correctly, the answer is "you don't distinguish them" :
The exact same action is executed from the controller, rendering the exact same view. The difference is the collection of 'fichas' that get sent to the view:
- in the first case, all fichas are available in the view
- in the second case, only the 'fichas' related to the 'cadeira' are available in the view (e.g. /cadeira/1/fichas will display only the 'fichas' related to the 'cadeira' with id 1)
To determine which records to show (e.g.) in an index view, you can do something like this:
unless cadeira_id = params[:cadeira_id]
#fichas = Ficha.all
else
#fichas = Cadeira.find(cadeira_id).fichas
end
The rest is up to the view: it should render fichas the same way, you just chose which records are actually made available to it.