I found the following in the FAQ after sorting out a bug.
It’s possible that you are trying to paginate a static Array instead of performing a paginated query in the database. For instance, chaining a paginate call after an Active Record find or all methods is wrong:
The above line will return the desired result but defeats the purpose of pagination. Here, the find query will first load all the records from the database, which is dangerous and should be avoided.
My question is why is it dangerous to paginate a find?
Pagination is meant to prevent unnecessary db load: you only want some elements from the db, so you only load them.
Using find you load everything then you kind of sort.
Dangerous == Heavy db load and thus potential crash.
Related
I'm trying to generalize some logic to do some manipulation to a ActiveRecord::Relation. Issue is that the aim is to prevent authorization issues, so the flag needs to be set whenever a new ActiveRecord::Relation is instantiated or changed, but I'm not sure how to access the ActiveRecord::Relation data. I think some pagination gems might have a solution, but unsure.
Specific issue is that for Pundit we use something like:
policy_scope(Model)
Ignoring the specifics of exactly how policy_scope works (as it's pretty flexible), it might modify the query to use something like:
Model.where(user_id: current_user.id)
And yes, some care is needed to ensure it doesn't perform a union rather than an intersect on the ids, but that is another matter and handled within the policy itself.
To scope a Model or database query in general to a specific scope. I'd like to add a check on that to ensure and verify that all database queries are scoped. A way this could be done would be to add a flag of some sort to the query itself automatically an unflag it if is scoped, with an error being generated if the query is ran while it is flagged.
THe problem trying to solved here is that it can be very problematic if certain database queries are not scoped when it comes to multi-tenanting and other use cases.
I have Rails 3 project that I updated to 5, that uses Mongoind instead of Active Record. I'm trying to implement fragment caching.
My understanding is, that with ActiveRecord, even if I have something like
#films = Film.all in a controller, but never use #films in the view, the query won't actually run. Hence, if I cache #films in the view, on the second request, it'll be read from cache, and query isn't going to run.
This is how I think ActiveRecord works.
Now to Mongoid. I cache variable in the view, but even though it's being read from cache, the query still hits db.
My question is, is there a way to avoid that with Mongoid?
Or am I missing something in terms of caching?
I tried searching online, but there isn't much on Rails Mongoid caching, not to mention, anything written after 2012.
In a stats part of a Rails app, I have some custom SQL calls that are called with ActiveRecord::Base.execute() from the model code. They return various aggregates.
Some of these (identical) queries are run in a loop in the controller, and it seems that they aren't cached by the ActiveRecord query cache.
Is there any way to cache custom SQL queries within a single request?
Not sure if AR supports query caching for #execute, you might want to dig in the documentation.
Anyway, what you can do, is to use memoization, which means that you'll keep the results manually until the current request is over.
do something like this in your model:
def repeating_method_with_execute
#rs ||= ActiveRecord::Base.execute(...)
end
This will basically run the query only on the first time and then save the response to #rs until the entire request is over.
If I am not wrong, Rails 2.x already has a macro named memoization on ActiveRecord that does all that automatically
hope it helps
Is there a technique that I can use in Rails so that whenever a simple "find" is performed on a Model object, memcached is first searched for the result, only if no result is found will a query by then made to the database?
Ideally, I'd like the solution to be implicit, so that I can just write Model.find(id), it first checks the cache and if a database query is required that the object returned is then added to the cache i.e. I don't need to wrap the Model.find(id) with additional code to check the cache for matching contents.
Thanks!
http://github.com/ngmoco/cache-money is the way to go
I have a number of custom find_by_sql queries in Rails. I would like to use eager loading with them but there doesn't seem to be a good way to do this.
I have seen the eager_custom.rb file floating around and it doesn't seem to work with Rails now. It appear Rails does eager loading differently now, using 2 queries (the regular query plus a query where the 'id IN' the ids from the first query), instead of the single join query used in the past.
My question is if I do a custom SQL query, then do 'id IN' query, is there a way to add back associated objects into the initial query results?
For example I have topics loaded with find_by_sql, then I find topic images where the topic id is in the topics ids, is there a way to add the images manually back to the topics?
Thanks
As you noticed, in Rails 2.1 a new kind of eager/pre-loading was introduced which uses multiple queries with id IN (...). This method is usually faster, especially when there are multiple associations being pre-loaded. You can use this functionality manually with find_by_sql by using the preload_associations class method inherited from ActiveRecord (not recommended). For example:
class Person
def self.find_a_special_group
people = find_by_sql("...")
preload_associations(people, [:jobs, :addresses])
return people
end
end
The preload_associations method is protected, so you must call it from within the class, and it takes (1) an array of objects, (2) an array, hash, or symbol of associations (same format as find's :include option), and (3) an options hash. See the documentation for the ActiveRecord::AssociationPreload::ClassMethods module for more details.
However, having said all of that, this technique is certainly undesirable as the Rails documentation discourages programmers from using preload_associations directly. Are you sure you have to use find_by_sql? Are you sure you know all of the options find takes? (:select, :from, :joins, :group, :having, etc) I'm not saying you don't need find_by_sql, but it might be worth a few minutes to make sure.